Using RTF custom metadata fields

Some time ago I refused to use such fields, because there were problems with changing them via AppleScript: you couldn’t delete, change or add it to the record. All the more if you have just one such field among 20 others - you could get problems for all of them, e.g. setting custom meta data, containing RTF field results in an error. So, too many problems in exchange to what? You still have “not-so-nice” plane text fields.

Now with 3.7 version we have the option to index and account all the links in such fields as if they were in the document itself. So, if you cannot insert the links to the document (like EML file) or just don’t want them there - you can insert it in a such RTF custom field. What is important - is that when you read incoming links to a given file, you get the direct files relating to it. I mean that in previous versions you could do it only via separate intermediate annotation files. And this is a serious game changer… You can build a network with ANY files in your DB and outside directly.

So, I’d like to return to this RTF custom fields issue: is there a stable way to add/modify/delete them?

Standard function add custom meta data goes with ‘handler error’, though changes the value somehow…

“Batch Processing” hangs DEVONthink trying to change RTF field…

1 Like

@cgrunenberg, @BLUEFROG, do you have any thoughts or solutions on this?

Not via AppleScript. But you could also use other custom metadata types, e.g. either Item Link or URL containing item links. These links would be indexed too.

Is Batch Processing intended to work with RTF fields? Trying to do it hangs DT…

DEVONthink shouldn’t freeze but it’s unclear whether it should be possible without a screenshot. Could you please launch Apple’s Activity Monitor application (see Applications > Utilities), select the frozen app in the list of processes, choose the menu item View > Sample Process and send the result to cgrunenberg - at - devon-technologies.com? Thanks in advance!

All sent.
Remade my old scripts (inserted tell blocks), they throw error -10000 but work fine )

Here is my contribution, while Batch Processing is under arrest )

-- Script to change Custom Meta Data in a Batch
-- Created by Silverstone on 12.11.2019
-- Updated on 23.04.2021

use AppleScript version "2.7"
use application "LNSOSAX"
use application "SatimageOSAX"
use scripting additions
use script "Dialog Toolkit Plus" version "1.1.0"

tell application id "DNtp"
	set theRecords to get selection
	if (count of theRecords) > 0 then
		
		-- Setting Up the Dialog
		set theTop to 0
		set accViewWidth to 400
		set theLabelStrings to {"Identifier:", "From:", "To:"}
		set maxLabelWidth to max width for labels theLabelStrings
		set controlLeft to maxLabelWidth + 8
		
		set {ToField, ToLabel, theTop, fieldLeft} to create side labeled field "" placeholder text "Leave Empty to Delete the Value" left inset 0 bottom (theTop + 12) total width accViewWidth label text (item 3 of theLabelStrings) field left controlLeft
		
		set {FromField, FromLabel, theTop, fieldLeft} to create side labeled field "" placeholder text "Look for Specific Values?" left inset 0 bottom (theTop + 12) total width accViewWidth label text (item 2 of theLabelStrings) field left controlLeft
		
		set {IdentifierField, IdentifierLabel, theTop, fieldLeft} to create side labeled field "" placeholder text "As in DEVONthink Preferences" left inset 0 bottom (theTop + 12) total width accViewWidth label text (item 1 of theLabelStrings) field left controlLeft
		
		-- Window Title and Options Description
		set {theRule0, theTop} to create rule (theTop + 20) rule width accViewWidth
		set TitleMessage to "You are about to change Custom Meta Data" & linefeed & "for " & (count of theRecords) & " selected Record(s)"
		set LabelMessage to "Possible options are as follows:" & linefeed & linefeed & "'From' is not empty and 'To' is not empty:" & linefeed & "Script will replace the Value with 'To' only if it finds the Records with the Value, specified in 'From'" & linefeed & linefeed & "'From' is empty and 'To' is not empty:" & linefeed & "Script will replace the Value with 'To' in All selected Records" & linefeed & linefeed & "'From' is not empty and 'To' is empty:" & linefeed & "Script will delete the Values only if it finds the Records with the Value, specified in 'From'" & linefeed & linefeed & "'From' is empty and 'To' is empty:" & linefeed & "Script will delete the Values in All selected Records" & linefeed & linefeed & "* The format for entering a Date is: 'Day-Month-Year' all in numbers"
		set {MainLabel, theTop} to create label LabelMessage bottom theTop + 14 max width accViewWidth control size small size aligns left aligned
		set {MainMessage, theTop} to create label TitleMessage bottom theTop + 14 max width accViewWidth aligns center aligned control size large size with bold type
		
		set {theButtons, minWidth} to create buttons {"Cancel", "GO"} default button 2 given «class btns»:2
		set allControls to {IdentifierField, IdentifierLabel, FromField, FromLabel, ToField, ToLabel, MainLabel, MainMessage, theRule0}
		set {buttonName, controlsResults} to display enhanced window "Batch Change of Custom Meta Data" acc view width accViewWidth acc view height theTop acc view controls allControls buttons theButtons with align cancel button
		
		-- Processing Dialog Results
		if buttonName is "GO" then
			set {theID, theFrom, theTo} to {item 1, item 3, item 5} of controlsResults
			-- Converting String to Date if Date format is detected
			set theFrom to my IsTheDate(theFrom)
			set theTo to my IsTheDate(theTo)
			show progress indicator "Changing Custom Meta Data…" steps (count of theRecords) with cancel button
			set theNumber to 0
			repeat with theRecord in theRecords
				step progress indicator "(" & (theNumber + 1) & " of " & (count of theRecords) & "): " & ((filename of theRecord) as string)
				if theFrom is "" then
					if theTo is not "" then
						-- Replacing all Selected with 'To'
						my SetCustomMD(theID, theTo, theRecord)
					else
						-- Deleting CMD in All Selected
						my DeleteCustomMD(theID, theRecord)
					end if
				else
					if theTo is not "" then
						-- Setting specified CMD to 'To' if it matches the Search criteria in 'From'
						my SetFoundCustomMD(theID, theFrom, theTo, theRecord)
					else
						-- Deleting specified CMD if it matches the Search criteria in 'From'
						my DeleteFoundCustomMD(theID, theFrom, theRecord)
					end if
				end if
				set theNumber to theNumber + 1
			end repeat
			hide progress indicator
		end if
	else
		display dialog "Select Items in DEVONthink" with title "No Selection" buttons {"OK"} default button "OK"
	end if
end tell

-- Setting specified CMD
on SetCustomMD(theLabel, theValue, theDoc)
	tell application id "DNtp" to set theFields to custom meta data of theDoc
	try
		theFields
	on error number -2753
		set theFields to {}
	end try
	set theField to {}
	set theField to set user property ("md" & theLabel) in theField to theValue
	set theFields to theField & theFields
	try
		tell application id "DNtp"
			set custom meta data of theDoc to {}
			set custom meta data of theDoc to theFields
		end tell
	end try
end SetCustomMD

-- Deleting specified CMD
on DeleteCustomMD(theLabel, theDoc)
	tell application id "DNtp" to set theFields to custom meta data of theDoc
	try
		theFields
	on error number -2753
		set theFields to {}
	end try
	if theFields is not {} then
		try
			set theValue to get user property ("md" & theLabel) in theFields
		on error
			return
		end try
		set theFields to delete user property ("md" & theLabel) in theFields
		try
			tell application id "DNtp"
				set custom meta data of theDoc to {}
				set custom meta data of theDoc to theFields
			end tell
		end try
	end if
end DeleteCustomMD

-- Setting specified CMD if it matches the Search criteria
on SetFoundCustomMD(theLabel, theSearch, theReplace, theDoc)
	tell application id "DNtp" to set theFields to custom meta data of theDoc
	try
		theFields
	on error number -2753
		set theFields to {}
	end try
	if theFields is not {} then
		set theField to {}
		try
			set theFound to get user property ("md" & theLabel) in theFields
		on error
			return
		end try
		if theFound is theSearch then
			set theField to set user property ("md" & theLabel) in theField to theReplace
			set theFields to theField & theFields
			try
				tell application id "DNtp"
					set custom meta data of theDoc to {}
					set custom meta data of theDoc to theFields
				end tell
			end try
		end if
	end if
end SetFoundCustomMD

-- Deleting specified CMD if it matches the Search criteria
on DeleteFoundCustomMD(theLabel, theSearch, theDoc)
	tell application id "DNtp" to set theFields to custom meta data of theDoc
	try
		theFields
	on error number -2753
		set theFields to {}
	end try
	if theFields is not {} then
		try
			set theFound to get user property ("md" & theLabel) in theFields
		on error
			return
		end try
		if theFound is theSearch then
			set theFields to delete user property ("md" & theLabel) in theFields
			try
				tell application id "DNtp"
					set custom meta data of theDoc to {}
					set custom meta data of theDoc to theFields
				end tell
			end try
		end if
	end if
end DeleteFoundCustomMD

-- Converts the String to the Date if the String was entered in Date format 'day-month-year' (only date part), otherwise returns the input
on IsTheDate(DateString)
	set theF to find text "^(?:(?:31(\\/|-|\\.)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/|-|\\.)(?:0?[13-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29(\\/|-|\\.)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/|-|\\.)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$" in DateString with regexp and all occurrences
	if theF is not {} then
		set theDate to date DateString
		return theDate
	else
		return DateString
	end if
end IsTheDate