How to work with attributes from Hazel in a js script

Get help. Get answers. Let others lend you a hand.

Moderator: Mr_Noodle

I do not really understand how passing in attributes into a javascript works.

I want to rename my file via regex, hence I am using javascript to do the complex renaming for me.
I want to import the name of the file as a variable, and export the name in the newName variable.

This is what it looks like now:
https://dl.dropboxusercontent.com/u/81328/hazel_js.png

This is my script:
Code: Select all
// Get the first entry of the inputAttributes
var name = inputAttributes[0];

// Set up regex queries
var dateQuery = /_(\d\d)\.(\d\d)\.(\d\d\d\d)_/g,
    numberQuery = /Nr\.(\d\d\d)/g

// Regex work
var date = dateQuery.exec(name),
    number = numberQuery.exec(name)[1];

// Define string variables
var day = date[1],
    month = date[2],
    year = date[3];

// Create output string and put it in an array, named hazelOutputAttributes
var hazelOutputAttributes = [year+'-'+number+' Kontoauszug '+day+'-'+month+'-'+year];

return true;


What am I doing wrong?
Do I use the correct names for the input and output variables?
Henno
 
Posts: 2
Joined: Sun Jun 07, 2015 9:08 am

Did it.

Code: Select all
var name = inputAttributes[0];

var dateQuery = /_(\d\d)\.(\d\d)\.(\d\d\d\d)_/g,
    numberQuery = /Nr\.(\d\d\d)/g

var date = dateQuery.exec(name),
    number = numberQuery.exec(name)[1];

var day = date[1],
    month = date[2],
    year = date[3];

return {'hazelOutputAttributes': [year+'-'+number+' Kontoauszug '+day+'-'+month+'-'+year]};
Henno
 
Posts: 2
Joined: Sun Jun 07, 2015 9:08 am

Glad you got it working but giving it a glance, are you sure that isn't something you can do via Hazel's built-in matching/renaming functions?
Mr_Noodle
Site Admin
 
Posts: 11872
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Henno wrote:Did it.

Code: Select all
var name = inputAttributes[0];

var dateQuery = /_(\d\d)\.(\d\d)\.(\d\d\d\d)_/g,
    numberQuery = /Nr\.(\d\d\d)/g

var date = dateQuery.exec(name),
    number = numberQuery.exec(name)[1];

var day = date[1],
    month = date[2],
    year = date[3];

return {'hazelOutputAttributes': [year+'-'+number+' Kontoauszug '+day+'-'+month+'-'+year]};


I'm very new to this but seem to be close to a solution...

I'm working on a project to convert six years of NeatWorks scanned files, all named with GUID filenames, into files renamed using rearranged "TITLE" metadata from within the PDF files.

QUESTION: How do I assign the new filename parsed and reformatted by my Javascript after my Javascript returns with the new filename?

I've embedded the Javascript in a Hazel rule, but don't know how to apply the new filename passed back by the Javascript to rename the file...

Here is my Javascript:

Code: Select all
function hazelMatchFile(theFile, inputAttributes)
{
   //-- Add your logic here.
   //-- 'theFile' is an alias to the file that matched.
   //-- 'inputAttributes' is an JavaScript array of the values of any attributes you told Hazel to pass in.
   //-- Make sure to return true or false (or optionally a record) to indicate whether the file passes this script

function Left(str, n){
   if (n <= 0)
       return "";
   else if (n > String(str).length)
       return str;
   else
       return String(str).substring(0,n);
}
function Right(str, n){
    if (n <= 0)
       return "";
    else if (n > String(str).length)
       return str;
    else {
       var iLen = String(str).length;
       return String(str).substring(iLen, iLen - n);
    }
}


var sTitle = inputAttributes[0];

/* ===========================================
Note: All oldTitles assigned by Neatworks look like this:
          'Neat Document MyFileName Here 12 19 2012' or
          'Neat Receipt MyFileName Here 12 19 2012 $200.00''
=========================================== */

var oldTitle = sTitle;
var titleDate = Right(oldTitle,10);
var titleText = Left(oldTitle, oldTitle.length-11);
titleText = titleText.replace('Neat Document ','')
titleText = titleText.replace('Neat Receipt ','')
var newTitle = titleDate.substring(6,10) +'-'+ titleDate.substring(0,2) +'-'+ titleDate.substring(3,5) +' '+ titleText ;


/*================  This code allowed me to test the script in the OS X script editor ===============
debugger

app = Application.currentApplication()
app.includeStandardAdditions = true
//app.say('Hello world')
app.displayDialog('newTitle = ', {
    withTitle: 'Debugging',
    defaultAnswer: newTitle
})
==================*/

return {'hazelOutputAttributes': [newTitle]};

}
   
DaveB
 
Posts: 25
Joined: Sat Apr 02, 2016 7:56 pm

I believe you emailed support? If so, I've already answered you there and again, I believe it an be done without a script using Hazel's built-in pattern support.
Mr_Noodle
Site Admin
 
Posts: 11872
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Thanks for your reply here and via support email and forgive my double posting. I found this post online after submitting my support request and it seemed on-topic.

I have reviewed the pattern matching feature and it may be an alternate method for renaiming my files based on PDF metadata. But I already am so close to getting my Javascript to work, I'd like to discover why the renamed value is not returning from my Javascript. It may help others to discuss it here.

My rule is defined to apply to all files of the type "PDF".
And then to Do the following to the matched files:
Run Javascript - embedded script - with input and output attributes "Title" and "NeatName"
Then, Rename with Pattern - NeatName Extension

But when I copy files to the watched folder, the files are renamed with empty filenames so they end up with only file extensions.

It seems that NeatName is returning with a null or empty string value.

Here's my script:

Code: Select all
function hazelMatchFile(theFile, inputAttributes)
{
   //-- Add your logic here.
   //-- 'theFile' is an alias to the file that matched.
   //-- 'inputAttributes' is an JavaScript array of the values of any attributes you told Hazel to pass in.
   //-- Make sure to return true or false (or optionally a record) to indicate whether the file passes this script


var sTitle = inputAttributes[0];


function Left(str, n){
     if (n <= 0)
       return "";
   else if (n > String(str).length)
       return str;
   else
       return String(str).substring(0,n);
}
function Right(str, n){
    if (n <= 0)
       return "";
    else if (n > String(str).length)
       return str;
    else {
       var iLen = String(str).length;
       return String(str).substring(iLen, iLen - n);
    }
}


//var oldTitle='Neat Document Stanek Boyle 12 19 2012'
//var oldTitle='Neat Receipt Stanek Boyle 12 19 2012 $ 240.00'

var oldTitle = sTitle;

var n = oldTitle.indexOf("$");

if (n >= 0) {
   oldTitle = oldTitle.substring(0,n-1);
}

var titleDate = Right(oldTitle,10);
var titleText = Left(oldTitle, oldTitle.length-11);
titleText = titleText.replace('Neat Document ','')
titleText = titleText.replace('Neat Receipt ','')
var newTitle = titleDate.substring(6,10) +'-'+ titleDate.substring(0,2) +'-'+ titleDate.substring(3,5) +' '+ titleText;

/*================
debugger

//console.log("Why isn't this being called?")

app = Application.currentApplication()
app.includeStandardAdditions = true
//app.say('Hello world')
app.displayDialog('newTitle = ', {
    withTitle: 'Debugging',
    defaultAnswer: newTitle
})
==================*/

return {'hazelOutputAttributes': ['newTitle']};

}



I have tested a bare-bones, simplified version of this script to return a hard-coded string just to troubleshoot but am not able to pass any output attribute value back that gets used in the subsequent renaming step.

It seems that Hazel is not returning the output attribute from the Javascript.

What am I doing wrong?

Thanks for your help!
DaveB
 
Posts: 25
Joined: Sat Apr 02, 2016 7:56 pm

Did you specify the output attributes in the UI? When editing the script, there's a button that will bring up a UI where you can tell Hazel what those attributes are. Otherwise, Hazel has no way of knowing.
Mr_Noodle
Site Admin
 
Posts: 11872
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Did you specify the output attributes in the UI? When editing the script, there's a button that will bring up a UI where you can tell Hazel what those attributes are. Otherwise, Hazel has no way of knowing.


Hello Paul,

Yes I selected an input attribute from the UI called "Title" and I defined an output attribute that I called "NeatName".

My JavaScript converts the "Title" metadata found inside the PDF from either:
"Neat Document filename sample 12 02 2012"
Or "Neat Receipt filename sample 12 02 2012 $ 240.00"
into 2012-02-12 filename sample".

Then in the subsequent Renaming action, I selected the text output attribute "NeatName" and "Ext" as the components of the new filename. I can upload screenshots of the UI showing my rule definition if that will help.

In my Javascript, I have, "return {'hazelOutputAttributes': ['newTitle']};"

I expect that value to be substituted for "NeatName" once the script runs. Is my syntax correct in the script?
Do I need to define a variable in the script at "NeatName" instead of "newTitle"?
Should I be able to pass a sting value back from the script?

I really appreciate you responses and hope I'm getting closer to a solution. This renaming script will ultimately convert thousands of GUID named document and receipts stored as PDFs that were created by NeatWorks.

Once I am successful, I plan to write up a detailed article "Paperless Archive Migration from NeatWorks to Evernote Using Hazel", and submit it to the Paperless forums. In it I'll be describing how to abandon NeatWorks in favor of alternative file and folder-based archives or an Evernote based paperless archive.

Neat Co. announce recently they are discontinuing their dual codebase solution for PCs and Macs, and are moving to a unified, cloud-based software as a service. I'm unhappy with that option, as I suspect many Mac NeatWorks users will be. So this data migration via Hazel may appeal to many of those disenfranchised NeatWorks users. I purchased Hazel because is also promises to be a key, core element in the day to day workflow of scanning and filing documents. you have a great product here...

Thanks again for your support!

-DaveB
DaveB
 
Posts: 25
Joined: Sat Apr 02, 2016 7:56 pm

Looking at your script again, I noticed it's a match script. That means you also have to pass a boolean value for hazelPassesScript to indicate whether the item matched the script or not. Without that I believe it indicates failure and it won't matter what output attributes you assigned.
Mr_Noodle
Site Admin
 
Posts: 11872
Joined: Sun Sep 03, 2006 1:30 am
Location: New York City

Thank you for you help, I've got my entire Neatworks archive converted into a file system archive that's nicely renamed based on the metadata keywords found inside each PDF. Your support was much appreciated!

The problem with my JavaScript ended up being my own ignorance. I started from an example of an external JavaScript but was embedding the code in my rule. One I re-read the instructions I realized the function wrapper needed to be removed, and the embedded script began working.

It's a learning curve, but now I'm on my way.

Thanks again.

DaveB
DaveB
 
Posts: 25
Joined: Sat Apr 02, 2016 7:56 pm


Return to Support

cron