This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Unable to Create New File in Workflow from a Template

I'm trying to create a new document from a template when another object enters a specific workflow state.  I couldn't find a way to easily create the document from the template so I am trying to use the information on copying a file on the following page:

https://developer.m-files.com/Samples-And-Libraries/Samples/Processes/Copying-Objects/

The code below performs the following actions:

  1. Finds the template.
  2. Copies the properties.
  3. Removes unnecessary properties. I had a shorter list but I removed all the unnecessary ones trying to troubleshoot this issue.
  4. Change some of the remaining properties.
  5. Copy the files in the template to a new SourceObjectFiles object.
  6. Rename the file. There's only one in this example.
  7. Copy the ACL.
  8. Create the new object/file.
  9. Delete the temporary files from the server.

Every step goes through without errors.  I've verified all the objects that I'm passing to the CreateNewObjectExQuick have good data in them.  The function returns an ID for the newly created document.  However, nothing is actually created.  I cannot see anything in M-Files and the logs don't show that anything has been created.

The documentation for the CreateNewObjectExQuick function state "if the source file(s) cannot be uploaded the newly created object is left checked out and cannot be accessed from the M-Files UI".  This is the only clue that I have as to why it may not be working.  However, I have verified all the data in the SourceObjectFiles object is accurate and pointing to the correct files in the Temp folder.  M-Files is able to access the folder because I see the file created then removed.  I have even tried the original CreateNewObject function, then checked in the object, with the same results.

I'm at a loss.  Does anyone have any ideas?

OPTION EXPLICIT

'# Define M-Files Property IDs #
DIM ARCHIVE_STATUS_ID : ARCHIVE_STATUS_ID = Vault.PropertyDefOperations.GetPropertyDefIDByAlias("PD.ArchiveStatus")
DIM DOCTYPE_ID : DOCTYPE_ID = Vault.PropertyDefOperations.GetPropertyDefIDByAlias("PD.DocumentType")
DIM JOB_NUMBER_ID : JOB_NUMBER_ID = Vault.PropertyDefOperations.GetPropertyDefIDByAlias("JobNumber")
DIM SALES_ORDER_ID : SALES_ORDER_ID = Vault.PropertyDefOperations.GetPropertyDefIDByAlias("SalesOrder")

'# Define M-Files Class IDs #
DIM ELECDOC_CLASS : ELECDOC_CLASS = Vault.ClassOperations.GetObjectClassIDByAlias("CL.ElectricalDocuments")

'# Create Archive Status Array #
Dim oArchiveStatus: Set oArchiveStatus = CreateObject("System.Collections.ArrayList")
oArchiveStatus.Add 57 '# Current #
'# Create Document Type Array #
Dim oDocumentType: Set oDocumentType = CreateObject("System.Collections.ArrayList")
oDocumentType.Add 174 '# Control Panel Checklist #

'# Create Search Conditions Object #
Dim oSearchConditions : Set oSearchConditions = CreateObject("MFilesAPI.SearchConditions")
'# Exclude Deleted Items #
oSearchConditions.Add -1, AddStatusSearchCondition(MFStatusTypeDeleted, MFConditionTypeEqual, MFDatatypeBoolean, False)
'# Add Electrical Documents Class to Search Conditions #
oSearchConditions.Add -1, AddPropertySearchCondition(MFBuiltInPropertyDefClass, MFConditionTypeEqual, MFDatatypeMultiSelectLookup, ELECDOC_CLASS)
'# Add Document Type Property to Search Conditions #
oSearchConditions.Add -1, AddPropertySearchCondition(DOCTYPE_ID, MFConditionTypeEqual, MFDatatypeMultiSelectLookup, oDocumentType)
'# Add Archive Status Property to Search Conditions #
oSearchConditions.Add -1, AddPropertySearchCondition(ARCHIVE_STATUS_ID, MFConditionTypeEqual, MFDatatypeMultiSelectLookup, oArchiveStatus)
'# Add IsTemplate Property to Search Conditions #
oSearchConditions.Add -1, AddPropertySearchCondition(MFBuiltInPropertyDefIsTemplate, MFConditionTypeEqual, MFDatatypeBoolean, True)

'# Get Search Results #
Dim oSearchResults : Set oSearchResults = Vault.ObjectSearchOperations.SearchForObjectsByConditions(oSearchConditions, 0, False)

If oSearchResults.Count = 0 Then
	Err.Raise MFScriptCancel, "Could not find the Control Panel Checklist Template."
ElseIf oSearchResults.Count > 1 Then
	Err.Raise MFScriptCancel, "Too many Control Panel Checklist Templates found. Only one template should be marked as 'Current'."
Else
	'# Found Checklist Template. Create New Checklist from Template. #
	Dim oChecklistTemplateObjVer : Set oChecklistTemplateObjVer = oSearchResults.Item(1).ObjVer
	Dim oChecklistTemplateProperties : Set oChecklistTemplateProperties = Vault.ObjectPropertyOperations.GetProperties(oChecklistTemplateObjVer, True)
	
	'# Copy Template Properties then Remove Unwanted Properties #
	Dim oNewChecklistProperties : Set oNewChecklistProperties = oChecklistTemplateProperties.Clone
	RemovePropertyValue oNewChecklistProperties, ARCHIVE_STATUS_ID
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefAccessedByMe
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefCreated
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefCreatedBy
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefIsTemplate
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefLastModified
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefLastModifiedBy
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefMarkedForArchiving
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefObjectChanged
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefOriginalPath
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefSizeOnServerThisVersion
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefSizeOnServerAllVersions
	RemovePropertyValue oNewChecklistProperties, MFBuiltInPropertyDefStatusChanged
	
	'# Set Property Metadata Fields #
	oNewChecklistProperties.SearchForProperty(JOB_NUMBER_ID).CloneFrom(PropertyValues.SearchForProperty(JOB_NUMBER_ID))
	oNewChecklistProperties.SearchForProperty(MFBuiltInPropertyDefNameOrTitle).Value.SetValue MFDatatypeText, "Test Checklist Document"
	oNewChecklistProperties.SearchForProperty(SALES_ORDER_ID).CloneFrom(PropertyValues.SearchForProperty(SALES_ORDER_ID))

	'# Copy Checklist Template Files #
	Dim oNewChecklistFiles : Set oNewChecklistFiles = GetObjectSourceFiles(oChecklistTemplateObjVer)
	oNewChecklistFiles.Item(1).Title = "Test Checklist Document"

	'# Copy Access Control List #
	Dim oAccessControlList : Set oAccessControlList = Vault.ObjectOperations.GetObjectPermissions(oChecklistTemplateObjVer).AccessControlList.Clone

	'# Create New Template in M-Files #
	Dim bSingleFileDocument : bSingleFileDocument = oNewChecklistProperties.SearchForProperty(MFBuiltInPropertyDefSingleFileObject).Value.Value
	Dim lNewID : lNewID = Vault.ObjectOperations.CreateNewObjectExQuick(oChecklistTemplateObjVer.Type, oNewChecklistProperties, oNewChecklistFiles, bSingleFileDocument, True, oAccessControlList)

	'# Delete Temporary Files #
	ClearTemporaryFiles(oNewChecklistFiles)
End If

Private Function AddPropertySearchCondition(iMFPropertyDef, iMFConditionType, iMFDataType, oSearchValue)
	'#################################################
	'# Purpose: Creates a SearchConditionEx object
	'#
	'# Parameters:
	'#   iMFPropertyDef - M-Files Property ID
	'#   iMFConditionType - M-Files MFConditionType Enumeration
	'#   iMFDataType - M-Files MFDataType Enumeration
	'#   oSearchValue - Value or Array of Values
	'#################################################
	Dim oSearchCondition : Set oSearchCondition = CreateObject("MFilesAPI.SearchCondition")

	oSearchCondition.Expression.SetPropertyValueExpression iMFPropertyDef, MFParentChildBehaviorNone, Nothing
	oSearchCondition.ConditionType = iMFConditionType
	If VarType(oSearchValue) <> 9 Then
	    '# oSearchValue is not an Array #
		oSearchCondition.TypedValue.SetValue iMFDataType, oSearchValue
	Else
		oSearchCondition.TypedValue.SetValue iMFDataType, oSearchValue.ToArray()
	End If

	Set AddPropertySearchCondition = oSearchCondition
End Function

Private Function AddStatusSearchCondition(iMFPropertyDef, iMFConditionType, iMFDataType, oSearchValue)
	'#################################################
	'# Purpose: Creates a SearchConditionEx object
	'#
	'# Parameters:
	'#   iMFPropertyDef - M-Files Property ID
	'#   iMFConditionType - M-Files MFConditionType Enumeration
	'#   iMFDataType - M-Files MFDataType Enumeration
	'#   oSearchValue - Value or Array of Values
	'#################################################
	Dim oSearchCondition : Set oSearchCondition = CreateObject("MFilesAPI.SearchCondition")

	oSearchCondition.Expression.SetStatusValueExpression iMFPropertyDef, Nothing
	oSearchCondition.ConditionType = iMFConditionType
	oSearchCondition.TypedValue.SetValue iMFDataType, oSearchValue

	Set AddStatusSearchCondition = oSearchCondition
End Function

Private Function GetObjectSourceFiles(oSourceObjVer)
	Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")
	
	'# Get the Temporary Folder Path #
	CONST TEMPFOLDER = 2 '# https://msdn.microsoft.com/en-us/library/a72y2t1c(v=vs.84).aspx #
	Dim sTempFolderPath: sTempFolderPath = oFSO.GetSpecialFolder(TEMPFOLDER).Path
	
	'# Get Files for Current ObjVer Object #
	Dim oFiles: Set oFiles = Vault.ObjectFileOperations.GetFiles(oSourceObjVer)
	
	' Create New SourceObjectFiles Collection #
	Dim oSourceFiles: Set oSourceFiles = CreateObject("MFilesAPI.SourceObjectFiles")
	
	'# Add Files to the New SourceObjectFiles Collection #
	Dim iCounter
	Dim oFile

	For iCounter = 1 To oFiles.Count
		Set oFile = oFiles.Item(iCounter)

		'# Download Current File to Temp Folder #
		Dim sTempFilePath: sTempFilePath = oFSO.BuildPath(sTempFolderPath, oFSO.GetTempName()) & "." & oFile.Extension
		Vault.ObjectFileOperations.DownloadFile oFile.ID, oFile.Version, sTempFilePath

		'# Create ObjectSourceFile for Current File #
		Dim oObjectSourceFile: Set oObjectSourceFile = CreateObject("MFilesAPI.SourceObjectFile")
		oObjectSourceFile.Extension = oFile.Extension
		oObjectSourceFile.SourceFilePath = sTempFilePath
		oObjectSourceFile.Title = oFile.Title
		
		'# Add ObjectSourceFile to ObjectSourceFiles Collection #
		oSourceFiles.Add -1, oObjectSourceFile
	Next

	'# Return ObjectSourceFiles Collection #
	Set GetObjectSourceFiles = oSourceFiles
End Function

Private Sub ClearTemporaryFiles(oObjectSourceFiles)
	Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")

	'# Delete the Files in the ObjectSourceFiles Collection from the Temp Folder #
	Dim iCounter, oFile
	For iCounter = 1 To oObjectSourceFiles.Count
		Set oFile = oObjectSourceFiles.Item(iCounter)
		If oFSO.FileExists(oFile.SourceFilePath) Then
			On Error Resume Next
			oFSO.DeleteFile oFile.SourceFilePath, True
			On Error Goto 0
		End If
	Next
End Sub

Private Sub RemovePropertyValue(ByRef oPropertyValues, iPropertyDef)
	'# Find Index of the Property Value (-1 if Not Found) #
	Dim iIndex: iIndex = oPropertyValues.IndexOf(iPropertyDef)
	If iIndex > -1 Then oPropertyValues.Remove iIndex
End Sub