One day early for S&TT, but I couldn't wait...
Ever since I read the post that Chris Blatnick put up last month about adding tagging to your mail file, I have been intrigued. I quickly did as he suggested and created a new toolbar button with the code he provided and starting tagging away.
I quickly realized that this was going to be a tedious process in a couple of ways if I was going one document at a time and had virtually no way of knowing whether the documents had been tagged. I of course don't want to, and can't, make design changes to the design elements of my mail file, but I could create a new view based off of an existing view then add a column for the tagging information and also some actions related to tagging, instead of just using the toolbar icon.
I created a new view based off the All Documents view (called it 'All by Tags') and threw 2 columns into it, in front of the Who column, one being a category totals column with detail rows hidden, and then a categorized column, showing multiple values as separate entries, and with the formula - @If(txt_customtags = ""; "*No tags applied";txt_customtags). This now brings the tags applied to the forefront, and also shows which emails do not have any tags applied yet, all together.
I modified the code for setting the tags on the document slightly resulting in this view action called "Tag Document":
REM {Get tags stored in database};
Tags := @GetProfileField("TagsProfile";"txt_CurrentTags";@UserName); REM {Get any tags from the selected document};
DocTags := txt_CustomTags;
Selection := @Prompt([OkCancelListMult]; "Select Tag(s)"; "Please select the tag(s) to apply to this document"; DocTags; @Trim("*-add new-*" : @Unique(Tags : DocTags)));
@If(Selection = 1;
@Return("");
@IsMember("*-add new-*"; Selection);
@Set("NewTag"; @Prompt([OkCancelEdit]; "Enter New Tag"; "Please enter the new tag(s) you would like to apply to this document. Separate tags with a comma"; ""));
"");
UpdatedList := @Trim(@Unique(@Replace(Selection; "*-add new-*"; "") : @Explode(NewTag;"," )));
FIELD txt_CustomTags := UpdatedList;
@SetProfileField("TagsProfile"; "txt_CurrentTags"; @Unique(UpdatedList : Tags); @UserName)
Then I wanted to be able to see the list of tags applied to a document (especially when it is more than one tag), so I created this action called "Display Tags":
@Prompt([Ok]; "This Document's Tag(s)"; "Tags applied to this document: " + @NewLine + @NewLine + @Implode(txt_CustomTags;@NewLine));
@True
Lastly, I wanted a way to clear all the tags as Chris suggested, so I create another action called "Clear Tags":
FIELD txt_CustomTags := @Unavailable;
@True
Now, back to what I mentioned earlier, this is all well and good, but what if I want to set a tag or various tags on a whole bunch of documents at once? Vitor Pereira suggested in a comment on the original post that perhaps this code coupled with a little bit of Chad Schelfhout's Edit Document Fields code could allow us to modify more than one document.
So I had a go at it...
Here's what I came up with, in an action called "Tag Multiple Documents":
REM {Get tags stored in database};
Tags := @GetProfileField("TagsProfile";"txt_CurrentTags";@UserName); Selection := @Prompt([OkCancelListMult]; "Select Tag(s)"; "Please select the tag(s) to apply to these documents"; ""; @Trim("*-add new-*" : @Unique(Tags)));
@If(Selection = 1;
@Return("");
@IsMember("*-add new-*"; Selection);
@Set("NewTag"; @Prompt([OkCancelEdit]; "Enter New Tag"; "Please enter the new tag(s) you would like to apply to this document. Separate tags with a comma"; ""));
"");
UpdatedList := @Trim(@Unique(@Replace(Selection; "*-add new-*"; "") : @Explode(NewTag;"," )));
REM {Unchangable constants};
cPromptTitle := @DbTitle + " - " + @ViewTitle;
cNoteEntryLength := 11;
cArraySeparator := ";";
cMaxSearchForSelectedDocs := 5520;
cCategoryNoteID := "NT00000000";
cPromptNewLineOne := @Char(13);
cPromptNewLineTwo := cPromptNewLineOne + cPromptNewLineOne;
cPromptTab := @Char(9);
cErrorInformation := "\"Error documents: \" + @Implode( @Unique( @Explode( ErrorNoteIDList ; cArraySeparator ; @False ) ) ; \", \" ) + cPromptNewLineOne + \"Not updated documents: \" + @Implode( @Unique( @Explode( ErrorNoteIDList ; cArraySeparator ; @False ) ) ; \", \" )";
REM {Store all Note IDs before manipulation in case field modifications cause categorized views or sorted columns to reorganize};
NoteIDList := @Text( @NoteID );
ErrorNoteIDList := "";
@Command([NavNextSelected]);
@UpdateFormulaContext;
REM {Start Looping Selected documents to gather all the documents that need to be updated.};
@While( ( @Left( NoteIDList ; cNoteEntryLength ) != ( @Text( @NoteID + cArraySeparator ) ) ) & ( @Length( NoteIDList ) < cMaxSearchForSelectedDocs ) ;
NoteIDList := NoteIDList + cArraySeparator + @Text( @NoteID );
NoteIDList := @ReplaceSubstring( NoteIDList ; cCategoryNoteID + cArraySeparator ; "" );
@Command([NavNextSelected]);
@UpdateFormulaContext
);
REM {Remove all category Note IDs};
NoteIDList := @ReplaceSubstring( NoteIDList ; cCategoryNoteID ; "" );
REM {Remove all duplicate Note IDs};
NoteIDList := @Unique( @Explode( NoteIDList ; cArraySeparator ; @False ) );
@StatusBar( "Found " + @Text( @Elements( NoteIDList ) ) + " documents." );
NotNoteIDList := "";
EditField := form;
REM {Loop through selected docs taking each NoteIDList out of the list as it is processed};
DocUpdateCount := 0;
DocNavigationCount := 0;
@While( DocUpdateCount < @Elements( NoteIDList ) ;
@If( @TextToNumber( @Text( @DocumentUniqueID ) ) != 0 ;
@Do(
NoteIDList := @Replace( NoteIDList ; @NoteID ; "" ) ;
NotNoteIDList := NotNoteIDList : @NoteID;
formulaResult := @Eval( @SetField("txt_CustomTags"; @Trim(@Unique(UpdatedList:txt_CustomTags))));
DocUpdateCount := DocUpdateCount + 1;
@UpdateFormulaContext
);
"")
);
@StatusBar( "Navigated through " + @Text( DocUpdateCount + DocNavigationCount ) + " documents." );
@SetProfileField("TagsProfile"; "txt_CurrentTags"; @Unique(UpdatedList : Tags); @UserName)
This last action does have some more work to be done on it, but it works (as far as I can tell) if you stick to the following rules:
- The set of selected documents must be contiguous (all together in the view)
- You must leave your cursor (highlight, whatever...) on the first document of the list of selected (checked) documents.
- The action doesn't de-select the documents once they have been modified, so you need to be careful to clear any selections before doing your next set of tagging (easy to do via Edit...Deselect All)
I'd love to hear if any of your try this set of functionality out and it works for you, and also if you can get around any of the shortcomings of my current code for tagging multiple documents at once, as this was a true trial and error (many, many errors) thing.
Special thanks to Chris Blatnick for putting this in front of us in the first place!