Author Topic: Custom script keywords for directory listing and loading text  (Read 14125 times)

0 Members and 1 Guest are viewing this topic.

Padanges

  • Newbie
  • *
  • Posts: 179
Custom script keywords for directory listing and loading text
« on: August 27, 2016, 07:59:14 AM »
Hi,
I want to write a script which by given BatchFile.Filename looks in current file directory for other files with the same name but different file extensions (let's call them "family files" :) ) and returns the number of them. How can I do that?
In addition to that, is it possible to load text lines into BatchFile.Filename DB entry's Info field if it finds file (among those listed) named, for example, "descript.ion"?

Thanks in advance.

RTT

  • Administrator
  • *****
  • Posts: 907
Re: Custom script keywords for directory listing and loading text
« Reply #1 on: August 28, 2016, 05:43:54 PM »
I want to write a script which by given BatchFile.Filename looks in current file directory for other files with the same name but different file extensions (let's call them "family files" :) ) and returns the number of them. How can I do that?
OT: Do you have experience with any coding language?

Here is a My Scripts script that works on that idea. For all the files selected in the grid, it will find the "family files" and report the number and names, if any found.
Code: [Select]
var wsh = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");

function getFolderFilesList(folderName, pattern) {
    var TemporaryFolder = 2;
    var ForReading = 1;
    var tmpFile = fso.GetSpecialFolder(TemporaryFolder) + '\\dirout.txt';
    var command = '%comspec% /c dir /on /b "' + folderName + '\\' + pattern + '">"' + tmpFile + '"';
    wsh.Run(command, 0, true);
    if (fso.FileExists(tmpFile)) {
        var f = fso.OpenTextFile(tmpFile, ForReading);
        var dirlist = [];
        while (!f.AtEndOfStream) {
            var filename = f.ReadLine();
            if (fso.FileExists(fso.BuildPath(folderName, filename))) {
                dirlist.push(filename);
            }
        }
        f.Close();
        fso.DeleteFile(tmpFile);
        return dirlist
    }
}

var ProgressBar = pdfe.ProgressBar;
ProgressBar.max = pdfe.SelectedFiles.Count;
for (var i = 0; i < pdfe.SelectedFiles.Count; i++) {
    ProgressBar.position = i + 1;
    var file = pdfe.SelectedFiles(i);
    var folderName = fso.GetParentFolderName(file.filename);
    var list = getFolderFilesList(folderName, fso.GetBaseName(file.filename) + '.*');
    if (list.length > 1) {
        var baseExt = fso.GetExtensionName(file.filename);
        var filename = fso.GetFileName(file.filename);
        var plist = [];
        for (var n = 0; n < list.length; n++) {
            if (fso.GetExtensionName(list[n]) !== baseExt && list[n] != filename) {
                plist.push(list[n]);
            }
        }
        if (plist.length > 0) {
            pdfe.echo(file.filename + ' has ' + plist.length + ' family files');
            for (n = 0; n < plist.length; n++) {
                pdfe.echo('   ' + plist[n]);
            }
        }
    }
}
pdfe.echo('All checked');
Quote
In addition to that, is it possible to load text lines into BatchFile.Filename DB entry's Info field if it finds file (among those listed) named, for example, "descript.ion"?
No, the filename field is read only, and I'm not getting the idea here!
From the script you can edit the metadata fields too, and so store theses names in a custom field.

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #2 on: August 29, 2016, 12:35:07 PM »
Quote
Do you have experience with any coding language?
Some. Nothing too extensive though.

Quote
No, the filename field is read only, and I'm not getting the idea here!
I'll try to say it differently: the idea is to have a column "Description" which would for a current entry look for *FileName*.description.txt (or, in general, for a "descript.ion" file) in the parent folder and (if the file exists) load the file content into the DB info field.

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #3 on: August 29, 2016, 12:36:51 PM »
OK, after checking-out your code I realized how can we make two quite general and useful tools: 1) Common folder files; 2) load entry info from file.

1) First of all, I need to get "related file" file mask prompt, where the mask default is "filename.*" (other possible cases: "filename.anyExactExt", "*.anyExactExt", "anyExactFilename.anyExactExt", "*.*"). Then to get common folder file list for the given pattern (excluding the current grid entry filename file from the list). Finally, print such results: $gridEntryFilename has $resultListFileCount related files: $resultList.

2) Get the filename and column name promt, where user specifies "ANYexactFILENAME.ANYexactEXT" and chooses current layout custom info field from combo-box. Then search for the given $filename in common folder and load it's content to given $column entry field. Finally, print such results: $gridEntryFilename related info file loaded; or: $gridEntryFilename related info file not found.

And that's a lot of new trick to learn...

RTT

  • Administrator
  • *****
  • Posts: 907
Re: Custom script keywords for directory listing and loading text
« Reply #4 on: August 30, 2016, 02:30:08 AM »
I'll try to say it differently: the idea is to have a column "Description" which would for a current entry look for *FileName*.description.txt (or, in general, for a "descript.ion" file) in the parent folder and (if the file exists) load the file content into the DB info field.
So you are talking about retrieving the metadata information stored in descript.ion files?
It seems these files don't have a fixed specification, so it would be tricky to parse the various variants. For descript.ion files with "Filename" "description" lines, doesn't seems too complicated to create such a script to put all the description data in a description named field. Have you tried already? Show me some code, if you are facing specific problems.

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #5 on: August 30, 2016, 11:24:47 AM »
Quote
Show me some code, if you are facing specific problems.

OK. Let's try. For the start, how do I get the promp for user input?
The lines:
Code: [Select]
var message='Specify related file name mask';
var defaultValue='textFile.*';
var input = prompt(message, defaultValue);
does not work. And then, how do I get the value into the log?
Code: [Select]
pdfe.echo(input);

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #6 on: August 30, 2016, 11:26:44 AM »
Quote
So you are talking about retrieving the metadata information stored in descript.ion files?
That could be the second step. For the start - it would be nice get any text file lines loaded into the entry info field. And how do you do that?

RTT

  • Administrator
  • *****
  • Posts: 907
Re: Custom script keywords for directory listing and loading text
« Reply #7 on: August 31, 2016, 12:44:36 AM »
OK. Let's try. For the start, how do I get the promp for user input?
The lines:
Code: [Select]
var message='Specify related file name mask';
var defaultValue='textFile.*';
var input = prompt(message, defaultValue);
does not work.
"prompt" is a method of the global root object "window", when scripts are running in a web browser. The My Scripts don't have this global root object, and that method is not implemented in the My Scripts pdfe root object.
The VBScript engine implements the InputBox and MsgBox (this one also directly available from pdfe.MessageBox) methods and here is a nice trick to make these available from JScript too.
Quote
And then, how do I get the value into the log?
Code: [Select]
pdfe.echo(input);
That will work.

Quote
So you are talking about retrieving the metadata information stored in descript.ion files?
That could be the second step. For the start - it would be nice get any text file lines loaded into the entry info field. And how do you do that?
Under the My Scripts batch tool, check the "File Summary Information to PDF metadata" sample script, for code about how to edit the metadata fields.

In the above script, that list the "family files", you have code on how to read text lines from an external file.

And check the "Merge by filename part match" sample script (check this forum topic for the history behind it) for ideas on how to develop a GUI for the tool  ;)

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #8 on: August 31, 2016, 01:48:39 PM »
OK! The I/O procedures are working now. Thanks! I expect no trouble with the rest of the first tool code. It should take a couple days to finish it and to test it out properly.
The second tool requires to get:
   1) the current grid layout custom field column name list
   2) the current the entry (pdfe.SelectedFiles(i)) info by specified custom field name (title?)
   3) to change that entry

Following your example in the "File Summary Information to PDF metadata" sample script I found that you predefine Column names using "FIELDS = ['Title', 'Subject', 'Author', 'Keywords', 'Comments'];". But can you get the list of current grid layout custom field column names? You also use Arguments property ("var Filename = pdfe.Arguments(i);") which in documentation is descibed as "Provides access to the entire collection of command-line parameters, in the order in which they were originally entered." while FileSummary ("var Summary = FileSummary.Read(Filename);") is undefined at all - but, I'm afraid, that doesn't help much. And finally, if I'm correct, to change an entry, you have to assign values and execute "FileMetadata.CommitChanges();". Could you help to find out how can we reference a specific column entry and the column name list?

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #9 on: August 31, 2016, 03:43:05 PM »
Quote
And check the "Merge by filename part match" sample script (check this forum topic for the history behind it) for ideas on how to develop a GUI for the tool  ;)
What a dirty trick!  ;D It's not a form - it' a (incognito) webpage as a form! ;D Thanks for sharing an idea but i prefer to continue with the MsgBox() code. Now, I just have to figure out how do I get that combo-box in there...
By the way, to resolve some code portability issues, you have to change line:
Code: [Select]
*/}.toString().replace(/^[^\/]+\/\*!?/, '').replace(/\*\/[^\/]+$/, '');to this:
Code: [Select]
*/}.toString().replace(/^[^\/]+\/\*!?/, '').replace(/\*\/[^\/]+$/, '').replace(/(\r\n|\n|\r)/gm,"");

RTT

  • Administrator
  • *****
  • Posts: 907
Re: Custom script keywords for directory listing and loading text
« Reply #10 on: September 01, 2016, 01:32:01 AM »
But can you get the list of current grid layout custom field column names?
No. You can get the list of all the available fields:
Code: [Select]
var FieldsInfo = pdfe.MetadataFieldsInfo;
for (var fIndex = 0; fIndex < FieldsInfo.count; fIndex++) {
    pdfe.echo(FieldsInfo(fIndex).caption + ' : ' + FieldsInfo(fIndex).PropertyName);
but there is no specific access to just the list of columns in the current grid layout, even because what changes when the script edits the metadata is the metadata stored in the DB and, eventually, in the file itself. The grid only reflects these changes.

Quote
You also use Arguments property ("var Filename = pdfe.Arguments(i);") which in documentation is descibed as "Provides access to the entire collection of command-line parameters, in the order in which they were originally entered."
This property exists only for compatibility with the WSH WScript Object, and contains the list of selected files. This way you can drop many readily available WSH scripts, and they will run without major changes.

Quote
while FileSummary ("var Summary = FileSummary.Read(Filename);") is undefined at all
You will find the implementation of the FileSummary object under the sample libraries, "File Summary Info" script. The main script links to that one, using the includes functionality.

Quote
And finally, if I'm correct, to change an entry, you have to assign values and execute "FileMetadata.CommitChanges();". Could you help to find out how can we reference a specific column entry and the column name list?
As said above, there is no way to know just what columns are showing. Why do you need to know that, when you have access to all the fields?
Code: [Select]
var FieldsInfo = pdfe.MetadataFieldsInfo;
for (var i = 0; i < pdfe.SelectedFiles.Count; i++) {
    var file = pdfe.SelectedFiles(i);
    pdfe.echo(file.filename);
    var metadata = file.metadata;
    for (fIndex = 0; fIndex < FieldsInfo.count; fIndex++) {
        //by name:
        pdfe.echo('     ' + FieldsInfo(fIndex).caption + ' : ' + metadata[FieldsInfo(fIndex).PropertyName]);
        //by index:
        //pdfe.echo('     ' + FieldsInfo(fIndex).caption + ' : ' + metadata(fIndex));
    }
}

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #11 on: September 01, 2016, 04:19:14 PM »
Quote
As said above, there is no way to know just what columns are showing. Why do you need to know that, when you have access to all the fields?
I was thinking about a combo-box which gives the list populated only by visible column names. Can we read visible column names from a layout grid data file?

Quote
but there is no specific access to just the list of columns in the current grid layout, even because what changes when the script edits the metadata is the metadata stored in the DB
Please correct me if I'm wrong, but columns in PDFe are PDF object metadata fields (excluding: F,FS,AN,FP,DL,DS,FD,NP) appended with the Custom fields and
listed in the order of their creation? And if (saved) layout grids simply toggle their visibility then custom grid layout lists those columns which are real DB
fields - in other words, removing a custom field removes its column from all the grid layouts at the same time?

Quote
You will find the implementation of the FileSummary object under the sample libraries, "File Summary Info" script.
Honestly, I still can't get my head around this... I need something like this:
Code: [Select]
var rowId = 0; // that's PDF file entry in the grid
var columnId = 1; // that's field (column) entry
// get the db metadata entry value
var value = pdfe.SelectedFiles(rowId).Metadata.Item(columnId);
pdfe.echo(value);
Could you help me a little with this?


P.S. try editing current grid layout while having deleted all custom fields ;) here be dragons.

RTT

  • Administrator
  • *****
  • Posts: 907
Re: Custom script keywords for directory listing and loading text
« Reply #12 on: September 02, 2016, 03:44:50 AM »
Can we read visible column names from a layout grid data file?
The layouts definitions are kept in the registry, at: HKEY_CURRENT_USER\SOFTWARE\PDFExplorer\GridLayout

Quote
Please correct me if I'm wrong, but columns in PDFe are PDF object metadata fields (excluding: F,FS,AN,FP,DL,DS,FD,NP) appended with the Custom fields and
listed in the order of their creation? And if (saved) layout grids simply toggle their visibility then custom grid layout lists those columns which are real DB
fields - in other words, removing a custom field removes its column from all the grid layouts at the same time?
Grid layouts just define how the full available metadata returned from a DB query is displayed.

Quote
Honestly, I still can't get my head around this... I need something like this:
Code: [Select]
var rowId = 0; // that's PDF file entry in the grid
var columnId = 1; // that's field (column) entry
// get the db metadata entry value
var value = pdfe.SelectedFiles(rowId).Metadata.Item(columnId);
pdfe.echo(value);
Could you help me a little with this?
The My Scripts API doens't take into account anything related to the grid layout. Things are just not connected. If you explain better what you want to achieve, maybe I can give you some workaround ideas.
But here is a dirty hack script that uses the last running session grid layout information (there is no way to know what's the current session layout), to list the data. Have fun :D
Code: [Select]
var WshShell = new ActiveXObject("WScript.Shell");
var LastSessionGridLayoutIndex = WshShell.RegRead("HKEY_CURRENT_USER\\SOFTWARE\\PDFExplorer\\GridLayout\\GridLayoutIndex");

//LastSessionGridLayoutIndex = 0;

if (LastSessionGridLayoutIndex > 3) {
    var layout = WshShell.RegRead("HKEY_CURRENT_USER\\SOFTWARE\\PDFExplorer\\GridLayout\\Custom\\str" + (LastSessionGridLayoutIndex - 4))
    layout = String.fromCharCode.apply(String, VB2JSArray(layout));
} else {
    var layout = WshShell.RegRead("HKEY_CURRENT_USER\\SOFTWARE\\PDFExplorer\\GridLayout\\Std\\S" + LastSessionGridLayoutIndex)
}

if (layout.indexOf('<column>') > 0) {
    var Columns = layout.match("<column>(.*?),</column>")[1].split(',')
} else {
    var Columns = layout.substr(layout.indexOf('=') + 1).split(',');
}

var ColumnNames = "Filename,File Path,Disk label,Disk serial,Size,Date,Title,Subject,Author,Keywords,Creator,Producer,Creation Date,Modification Date,Pages,Version,Security,Archive".split(',');
var FieldsInfo = pdfe.MetadataFieldsInfo;

var LayoutName = layout.substr(0, layout.indexOf('=<'));
for (var rowI = 0; rowI < pdfe.selectedfiles.count; rowI++) {
    var file = pdfe.selectedfiles(rowI);
    pdfe.echo(file.filename);
    var CalculatedIndex = 0;
    for (var columnI = 0; columnI < Columns.length; columnI++)
    if (Columns[columnI]) {
        if (Columns[columnI] > ColumnNames.length) {
            pdfe.echo('    ' + FieldsInfo(Columns[columnI] - 9).Caption + ' : ' + MetadataFromColmunIndex(file, Columns[columnI]));
        } else if (Columns[columnI] < 0) {
            pdfe.echo('    ' + 'Dynamic calculated' + ' : ' + MetadataFromColmunIndex(file, --CalculatedIndex));
        } else {
            pdfe.echo('    ' + ColumnNames[Columns[columnI] - 1] + ' : ' + MetadataFromColmunIndex(file, Columns[columnI]));
        }
    }
}

function MetadataFromColmunIndex(fileobj, index) {
    if (index < 0) {
        return fileobj.metadata.Calculated(Math.abs(index))
    } else switch (parseInt(index)) {
    case 1:
        return fileobj.filename.substr(fileobj.filename.lastIndexOf('\\') + 1);
    case 2:
        return fileobj.filename.substr(0, fileobj.filename.lastIndexOf('\\'));
    case 3:
    case 4:
        return "";
    case 5:
        return fileobj.FileSize
    case 6:
        return fileobj.DateLastModified;
    case 15:
        return fileobj.NumPages;
    case 16:
        return fileobj.metadata.version
    case 17:
        return fileobj.metadata.EncryptLevel
    case 18:
        {
            var archive = fileobj.filename.match("<(.*?)>");
            if (archive) {
                return archive[1].substr(archive[1].lastIndexOf('.'))
            } else return '';
        }
    default:
        {
            if (index < 14) {
                return fileobj.metadata(index - 7)
            } else if (index > 18) {
                return fileobj.MetaData.Custom(index - 18)
            }
        }
    }
}

function VB2JSArray(objVBArray) {
    return new VBArray(objVBArray).toArray();

}
Quote
P.S. try editing current grid layout while having deleted all custom fields ;) here be dragons.
This one was ugly! Shame on me  :-[

Padanges

  • Newbie
  • *
  • Posts: 179
Re: Custom script keywords for directory listing and loading text
« Reply #13 on: December 16, 2016, 11:08:06 AM »
Quote
The VBScript engine implements the InputBox and MsgBox (this one also directly available from pdfe.MessageBox) methods and here is a nice trick to make these available from JScript too.
I've been using and occasionally modifying this code for a while now, but I haven't found out how to change/remove the (msgbox/edit) window icon in the upper left corner. I think it should be dependent on the main app (icon set) which is our PDFe. Maybe you have had tried to sort this out?

RTT

  • Administrator
  • *****
  • Posts: 907
Re: Custom script keywords for directory listing and loading text
« Reply #14 on: December 18, 2016, 01:19:56 AM »
Probably not possible without WinAPI function calls, something not readily available from COM automation scripts.