Grouping items by date opened or like a daily journal

The moment you open a record you’ll lose any indication about when it was opened in the past.

This could get you started Script: Add reference URL to aliases and create Smart Group.

Hi @pete31 - this is really useful.

I get too busy to record my chargeable time and this is a really useful way of telling me what I’ve worked on when it comes time to log billable time entries at the end of the day.

I tweaked it to put in the current time and database name (which tells me the matter name the record relates to) before each record.

Thankyou! Outstanding. :grinning: :clap:

1 Like

I love this script, and I’d like to add the timestamp to the list that you’ve mentioned. Please can you show me how you did this? I thought I’d be able to figure it out myself but I am new to scripts and couldn’t see what to do.

Hi @MsLogica

Sure - here’s the script with my additions. It’s probably a bit hacky (what little I know about scripting I’ve cobbled together, mostly from this forum) but it works with no problem for me. :slightly_smiling_face:


-- adapted from script posted on @pete31 Nov 2021: https://discourse.devontechnologies.com/t/grouping-items-by-date-opened-or-like-a-daily-journal/67424/18

property sortByLastOpened : true
property theExcludedDatabaseNames : {"_temp"}

on performSmartRule(theRecords)
	tell application id "DNtp"
		try
			repeat with thisRecord in theRecords
				if (name of database of thisRecord) is not in theExcludedDatabaseNames then
					
					set theHistoryRecord_Name to my formatDate(current date) & space & "Activity Record"
					set theResults to search "kind:markdown {any: name==" & theHistoryRecord_Name & " name==" & theHistoryRecord_Name & ".md}"
					
					if theResults ≠ {} then
						set theHistoryRecord to item 1 of theResults
						set theHistoryRecord_Text to plain text of theHistoryRecord
					else
						set theGroup to create location "/Daily Activity Record" in inbox
						set theHistoryRecord_Text to "<style> a {text-decoration: none;} </style>" & linefeed & linefeed & "# " & theHistoryRecord_Name & linefeed
						set theHistoryRecord to create record with {name:theHistoryRecord_Name, type:markdown, plain text:theHistoryRecord_Text, exclude from see also:true, unread:false} in theGroup
					end if
					
					set thisRecord_ReferenceURL to reference URL of thisRecord
					
					if thisRecord_ReferenceURL ≠ (reference URL of theHistoryRecord) then
						
						--added to original script:
						set {year:y, month:m, day:d, time:t} to (current date)
						set theTime to my secsToHMS(t as integer)
						set theDatabase to the name of current database
						--end addition

						set thisMarkdownLink to (theTime & ": " & "**" & theDatabase & "** : " & "[" & my escapeLinkName(name of thisRecord) & "](" & thisRecord_ReferenceURL & ")") as string
						if theHistoryRecord_Text does not contain thisRecord_ReferenceURL then
							set plain text of theHistoryRecord to theHistoryRecord_Text & linefeed & "* " & thisMarkdownLink & space & space
						else if sortByLastOpened then
							set plain text of theHistoryRecord to my updateOrder(theHistoryRecord_Text, thisRecord_ReferenceURL, thisMarkdownLink)
						end if
					end if
				end if
			end repeat
			
		on error error_message number error_number
			if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
			return
		end try
	end tell
end performSmartRule

on formatDate(theDate)
	set theYear to year of theDate as string
	set theMonth to ((month of theDate) as integer) as string
	if (count theMonth) < 2 then set theMonth to "0" & theMonth
	set theDay to day of theDate as string
	if (count theDay) < 2 then set theDay to "0" & theDay
	return theYear & "-" & theMonth & "-" & theDay
end formatDate

on escapeLinkName(theText)
	set d to AppleScript's text item delimiters
	repeat with thisCharacter in {"[", "]", "(", ")", ">"}
		set AppleScript's text item delimiters to {"\\" & thisCharacter, thisCharacter}
		set theTextItems to text items of theText
		set AppleScript's text item delimiters to "\\" & thisCharacter
		set theText to theTextItems as text
	end repeat
	set AppleScript's text item delimiters to d
	return theText
end escapeLinkName

--added to original script: this gets the current time
on secsToHMS(secs)
	--from <http://macscripter.net/viewtopic.php?id=27203>
	tell (1000000 + secs div hours * 10000 + secs mod hours div minutes * 100 + secs mod minutes) as string ¬
		to return text 2 thru 3 & ":" & text 4 thru 5 & ":" & text 6 thru 7
end secsToHMS

on updateOrder(theText, theReferenceURL, theMarkdownLink)
	set theDelimiters to {"(" & theReferenceURL & ")" & space & space & linefeed, "(" & theReferenceURL & ")" & space & space}
	set theTextItems to my tid(theText, theDelimiters)
	set theTextItems_modified to {}
	repeat with i from 1 to (count of theTextItems)
		set thisTextItem to item i of theTextItems
		set thisTextItem_Paragraphs to paragraphs of thisTextItem
		set thisTextItem_Paragraphs_Count to (count of thisTextItem_Paragraphs)
		if thisTextItem_Paragraphs_Count > 0 then
			if item -1 in thisTextItem_Paragraphs contains "x-devonthink" then
				set theTextItems_modified to theTextItems_modified & thisTextItem_Paragraphs
			else if thisTextItem_Paragraphs_Count > 1 then
				set theTextItems_modified to theTextItems_modified & items 1 thru -2 in thisTextItem_Paragraphs
			end if
		end if
	end repeat
	return my tid(theTextItems_modified, linefeed) & linefeed & "* " & theMarkdownLink & space & space
end updateOrder

on tid(theInput, theDelimiter)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	if class of theInput = text then
		set theOutput to text items of theInput
	else if class of theInput = list then
		set theOutput to theInput as text
	end if
	set AppleScript's text item delimiters to d
	return theOutput
end tid

Thank you so much for sharing this. Because I like to make myself suffer needlessly, I went through your code and @pete31’s code line by line to learn what was different (I am new to AppleScript).

I thought I’d implemented my code the same as yours, but there was a bit of a glitch yesterday where I managed to create 200 individual logs whilst I was doing some file amends :joy::rofl: I’ve corrected the code today and it’s all running smoothly now (as far as I can tell). And I’ve learnt that one tiny bit of code can have big consequences :grimacing:

3 Likes

I once misplaced a single forward slash in a UNIX command and deleted three years of research in about 30 seconds :flushed::cry:
:slight_smile:

And as I’ve said for years: In UNIX there is no forgiveness. :smiling_imp:

1 Like

Same - I understand about 85% of what @pete31 does, but it always works (at least, until I “improve” it). :roll_eyes:

Speaking as someone who suffers from sympathetic terror especially related to data loss, please tell us this was an “oops, time to get the backup drive” kind of situation and not a “oh…did I just…oh no, wait, damn, (gulp) uhm… (shreds all ID cards, books ticket to far far away land)” situation?

Do you really want to know? :stuck_out_tongue:

1 Like

I can’t speak for @BLUEFROG, but the only time I used rm -rf * being root on a UNIX system was also the moment we found out that the tape drive we used to make our backups was not working as expected.

That’s the kind of experience you do not what to have. It certainly helps to understand why backups are important, and why you should also make sure that you can restore from them. And I’m really happy that I don’t have to use tape drives anymore.

I am chuckling at this, but I’m also experiencing sympathetic terror :joy:

I was working on a server of a multi-national, multi-billion dollar corporation :flushed: The saving grace was it was only my data not theirs.

Which is why you’re not living under an assumed name in a place with no internet access and no extradition treaty?

2 Likes

Hola, I’d like to change the location where the group of history records is saved. This script defaults it to the inbox (which has enough unprocessed things in it without me creating more :face_with_peeking_eye:).

I can see what I need to change in the script - this bit where it says to create in inbox:

Have I understood that bit right?

What I cannot find is what term I use to identify my own database instead. Just typing in the name of the database doesn’t work, I’m guessing because AppleScript doesn’t understand that this is a database. What do I type in scripts to recognise a specific database please?

I tried to be clever and look up the DT script dictionary - I managed this but then the info in it was basically a foreign language to me and I didn’t understand what to do!

Use in database named "My Database"

1 Like

Gosh that was quick, thank you so much! It works :blush:

1 Like

Note: inbox is specifically the Global Inbox.
Databases have an incoming group, e.g., with a shortened form of using the database’s name…

tell application id "DNtp"
incoming group of database "24"
end tell

Rather bafflingly this script has stopped working today. I’ve not changed anything and haven’t actually been on the computer for the last 2 days, but I just opened DT to do something and got this error message: Expected end of line, etc. but found “"”.

I thought it would show me where the error is, but it sadly does not, and I don’t know what this error means. Any ideas?

Are you running the script from Script Editor or DEVONthink?