Grid layout editor

The grid layout editor is used to edit, or create new, grid layouts. A grid layout is a named set of rules, selectable from the grid layouts selector, that define how data is shown on the grid, enabling the definition of what metadata columns are visible, columns position, columns titles, columns data type and text alignment, dynamic calculated columns, file types visibility, and definition of calculations to show on the calculations panel.

This way users can create custom grid layouts more suitable to their metadata document management needs, than the 4 default included layouts provided by PDFE. Sometimes the use of various layouts extend the possibilities to mask same, or different subjects, metadata, to a grid presentation more suitable to the type of analyzes to perform at a given time.

Accessible from the grid layout sub-menu of the Edit menu, or from the grid layout selector context menu.

When creating a new grid layout it is important to give it a meaningful name, using the grid layout name field, so that later can be easily found in the layout selector.

The general options group, on the bottom, is used to define:

The InfoEdit script validator selector is used to associate a MyScripts script to the InfoEdit save changes action, so it can be used to pos-process the edited metadata, before it is saved. Can be used to validate/fix metadata fields (fix letter case, remove extra spaces, replace characters, etc.)  or to automatically fill additional metadata fields (such as the modification date, increment a metadata edited counter field, etc), or even, as example, update an external database to log the changes.

The script, that should be created and tested using the MyScripts editor, should have the basic structure of the next JScript example.

var changed = false;
for (var i = 0; i < pdfe.SelectedFiles.Count; i++) {
    var FileMetadata = pdfe.SelectedFiles(i).Metadata;

    //replace dashes with spaces, in the title field    
    var s = FileMetadata.Title.replace(/-/g, ' ');
    if (s != FileMetadata.Title) {
        FileMetadata.Title = s;
        changed = true;
    }

    //uppercase the subject field
    s = FileMetadata.Subject.toUpperCase();
    if (s != FileMetadata.Subject) {
        FileMetadata.Subject = s;
        changed = true;
    }

    //Set a Year named custom field 
    s = new Date().getFullYear();
    if (s != FileMetadata.Year) {
        FileMetadata.Year = s;
        changed = true;
    }
    if (changed) {
        FileMetadata.CommitChanges();
    }
}

The script will receive in the pdfe.SelectedFiles the file object of the PDF file the InfoEdit tool is editing, and its metadata is the new, not yet saved, metadata. The script can then validate/change it, as exemplified, and, if the CommitChanges method is invoked, the metadata saved will include these changes.

This type of script is also totally functional if used as a MyScripts batch tool, so it can be used to validate metadata on files already edited.

The columns tab sheet is used to define:

Dynamic Calculated Columns

These type of grid columns, defined by an eval expression that can access other columns data, are useful when there is a particular value that can be extracted, or computed, from one, or more, metadata fields, enhancing the functionality of that particular grid layout management functionality. When that value is presented in a grid column, it can be sorted and exported. This columns data only exits on the grid, and is dynamically calculated every time the grid refreshes, so values can change if eval expression includes variables that change with time.

Some typical examples of what one of these columns could be used for is to calculate the number of days that have passed since a date value set in one of the physical metadata fields, or to show a numeric value, gathered from other physical, or dynamic, grid columns, affected by a percentage, or another type of numeric calculation involving numeric values.

These eval expressions are not limited to dealing with numeric values. Manipulation of text is also a possibility, so can be used to find, extract, manipulate and present text gathered on other columns data.

Eval expressions of this examples, and full eval expressions syntax are shown and explained below.

Calculations panel

The calculations panel, defined from the Calculations grid layout editor tab sheet, are another type of dynamic calculation that a grid layout can be defined with.

This panel is accessible from a grid toolbar button that is only visible when this panel is configured in the active grid layout.

It can be used to present calculations that involve all the values of a particular column. Useful to present totals, or other statistics functions results. The above image, example of one of this calculations panel (in this case the default panel that is set with the standard grid layout) clearly exemplifies how it can be used.

To define a value on this panel there is only the need to add a new entry, set its name and define the eval expression. Values can be grouped, for better visual presentation, adding header fields to the panel.

Examples, eval expression syntax, and functions that can be used on this panel, are presented and explained below.

The standard grid layout, the one that has a default calculations panel defined, can be easily cloned, Edit>GridLayout>CloneCurrent, and, because the cloned layout can be edited, inspected to see how its calculations panel is defined.

Eval expressions syntax

Comments

Comments are ignored by the compiler. There are two ways to construct comments: text between a left brace and a right brace constitutes a comment. Also text between a double-slash and the end of the line constitutes a comment.

Types and expressions

Depending on the expression, the data value is ether a numeric or string type. For comparison operation (=, <> ,>= , <= , >, <) and addition, the expression evaluator tries to convert the operand first to numeric values and if this is impossible then to a string. For example: "123" + 321 returns 444, but "x123" + 321 results in "x123321".

Numeric literals (integer and real) can be represented in common decimal notation. The dollar-sign prefix indicates a hexadecimal numeral. The first hexadecimal digit after $ must be one of 0..9 - for example $0AF (not $AF).

String values can be enclosed in either double or single quotes. Two sequential apostrophes or double quotes in a same quoted string denote a corresponding single character. To specify symbol with special ASCII code use # symbol followed by corresponding integer constant.

There is no Boolean type. As in C language the evaluator treats zero value as False and nonzero as True.

Date and time are represented as a floating point value.

Operators

Numeric operators: +, - , * , /, % (or mod), \ (or div), ^ (raise to a power).

Comparison operators: =, <>, >, <, >=, <=.

Logical operators: & (or and), | (or or), xor, ! (or not).

Concatenation operator: @.

Difference in addition and concatenation operations is that @ always treats its operands as strings, i.e. "123" @ 321 results in "123321" (unlike it "123" + 321 returns 444).

Referencing grid column/row data

To reference a grid column or metadata field data we must use its defined constant name.
F = Filename, FP = File path, DL = Disk label, DS= Disk Serial, FS = File size, FD = File date, T = Title, S = Subject, A = Author, K = Keywords, C = Creator, P = Producer, CD = Creation date, MD = Modification date, NP = Number of document pages, V = File format version, E = Security level, AN = Archive name (for compressed archives), C# = Custom field, where # must be replaced by its index, e.g. C1, C2,.., D# = Dynamic calculated column, # must be replaced by its index, D1, D2. Circular references must be avoided or the program will lock.

When evaluating dynamic calculated columns expressions, these column reference constants names represent the string content of the current row being calculated. So, if in a dynamically calculated expression, a T constant is entered it will be replaced by the content of row 0 of Title column when calculating the result of the expression at row 0, and by the Title content of row 1 when calculating the result of the expression at row 1, etc..

When evaluating "calculation" expressions, these column reference constant names represent all of that column values array, when passed to functions with variable argument list, see statistical functions below ( e.g. Min(NP) ), or as the value at row 0, when used in single argument operation, e.g. NP*15.

Note: All metadata fields can be referenced by its constant name, even if they are not set to visible on the grid layout.

Supported functions

Grid data access functions:

grid.numrows - returns the number of filled rows on active grid.
grid.cell(colname,rowindex) - Use it to access the string within a particular Column/Row intersection define by the ColName and RowIndex respectively. ColName is the string name of the column coordinate of the cell, and RowIndex is the row coordinate of the cell. The first row is row zero.

Numeric functions:

Trigonometric, hyperbolic and invert functions:
sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), cosh(x), sinh(x), tanh(x), asinh(x), acosh(x), atanh(x)
Exponential and logarithmical functions:
log(x), lg(x) (log base 10), exp(x), sqrt(x)
Integer and factional part of number: int, frac
Absolute value: abs
Sign of a number: sign
Random value and initialization of the random number generator: rnd, randomize

Statistical functions (all statistical functions take variable argument list):

max(x1,x2,...) - maximum of passed values,
min(x1,x2,...) - minimum of passed values,
avg(x1,x2,...) - average value,
stddev(x1,x2,...) - standard deviation (unbiased),
stddevp(x1,x2,...) - standard deviation (biased),
sum(x1,x2,...) - sum of passed values,
sumofsquares(x1,x2,…) - sum of passed values squares
count(x1,x2,...) - count of passed values
variance(x1,x2,...) - variance (unbiased)
variancep(x1,x2,...) - variance (biased)

Logical functions:

iff(e,x,y) - checks the expression passed as e and returns x if it evaluates to true, or y if it evaluates to false.
isnumber(x) - returns true if x is number.

String functions:

chr(x) - returns a character with ASCII code x.
length(s) - length of the string.
trim(s), trimleft(s), trimright(s) - trims leading and/or trailing spaces and control characters from a string
uppercase(s), lowercase(s) - converts an ASCII string to upper(lower)case.
midstr(s,fron,len), leftstr(s,len), rightstr(s,len) - returns the substring of a specified length that appears at the specified position (start, end) of a string.
ReverseStr(s) - returns the string specified by s with the characters in reverse order.
pos(t, s) - returns the index value of the first character of t that occurs in s.
code(s) - returns the ASCII code of first character of string s.
stringofchar(c, count) - returns a string with a specified number of repeating characters.
concat(s1,s2,...) - concatenates an arbitrary number of strings.

Date and Time functions:

date(s) - converts string to numeric date-time value.
now - returns the current date and time.
dayofweek(d) - returns the day of the week represented by a value d. Returns a value between 1 and 7, where 1 indicates Monday and 7 indicates Sunday.
year(d), month(d), day(d), hour(d), minute(d), second(d), millisecond(d) - returns respective part of date-time value d.
isleapYear(n) - indicates whether a specified year n is a leap year.
encodedate(year, month, day) - returns a date-time value that represents a specified year, month and day.
daysbetween(now, then) - returns a double type value representing the difference, in days, between two DateTime values. DaysBetween counts only whole days. Thus, DaysBetween reports the difference between Dec 31, 1999 11:59 PM and Jan 1, 2000 11:58 PM as 0 because the difference is one minute short of an entire day.
dayspan(now, then) - returns a double type value representing the difference, in days, between two Date values. Unlike the DaysBetween function, which only counts whole days, DaySpan reports incomplete days as a fraction of an entire day.

Formatting functions:

format(s,x) - formats a floating point value x using the format string given by s. Uses the same format string as format Delphi FormatFloat function.
formatf(s,x) - formats a floating point value x using the format string given by s. Uses the same format string as format Delphi Format function.
formatdate(s,d) - formats a date-time value d using the format string given by s. Uses the same format string as format Delphi FormatDateTime function.
FormatFileSize(x) - formats a integer value representing a file size in bytes to human readable format.

Variables

There are two functions to define variables:

define("name", value) and defines("name1", "name2", "name3", ...).

Instead of defines() you can use the following syntax:

var "name1", "name2", "name3", … end.

To get/set value of variable use functions:

get("name") and set("name", value).

In place of get("name") you can use $name, and in place of set("name", value) - $name := value.

As set and get are functions, you can use an expression to specify variable name. Corresponding alternative syntax is $(expression).

There are two special functions for variable incrementing and decrementing:

inc('name') and dec('name'). Instead of function call you can use next syntax: $name++ and $name--.

Arrays support is not provided, but you can work with variables named 'n1', 'n2', 'n3' ... as with array. To reference element of such "array" use expression $('arrayname'@index) or $arrayname[index] for example $n[$i]. Two dimensional arrays should consist of variables 'x1_1', 'x1_2', 'x2_1' and so on. To reference element: $x[$i,$j] (equal to $('x'@$i@'_'@$j)). You can define multidimensional arrays in the same way.

Statements

There are five special functions treated as statements. In fact these functions are not real functions as they are compiled in special byte code.

Return procedure:

return(value) - stops evaluation and return value as a result of computation.

Compound statement:

block(p1,p2,p3,…) - returns value of last argument.

Predefined constants:

begin = block(
end = )

Corresponding alternative syntax:

begin p1; p2; p3; … end.

If statement

condition(expression, p1, p2) - returns p1 or p2 depending of expression value.

Predefined constants:

if = condition(
then = ,begin(
else = ),begin(
endd = ))
endif = ),0)

Corresponding alternative syntax:

if expression then p1 else p2 endd or
if expression then p1 endif.

Pay attention that in first case statement should end with endd as in fact if expression then p1 else p2 endd is equal to condition(expression, block(p1), block(p2)).

Difference between condition and iff functions is that iff computes both its branches and condition only one. For example

iff(1,message('1','1',0),message('0','0',0)) shows two message boxes and
if 1; message('1','1',0); message('0','0',0) end shows only first message box.

While statement

loop(expression, p)

Predefined constants:

while = loop(
do = ,begin(
wend = ))

Corresponding alternative syntax:

while expression do p wend.

Repeat statement

till(p, expression)

Predefined constants:

repeat = till(begin(
until = ),

Corresponding alternative syntax:

repeat p until expression end.

For statement

series(initialization, condition, increment, p)

Predefined constants:

for = series(
next = ))

Corresponding alternative syntax:

for initialization; condition; increment do p next

For statement is equal to C iterative loop. For example:

for $i := 1; $i <= 10; $i++ do $x[$i] := $i; next

All loop functions return the number of iterations done.

Examples:

Calculation expression to show the total number of bytes occupied by the files present in the active grid

FormatFileSize(Sum(fs))

Calculation expression to show the number of bytes occupied by the smallest file present in the active grid

FormatFileSize(Min(fs))

Calculation expression to show row and filename of first file with zero number of pages.

begin
var 'i','n' end;
$n:=grid.numrows;
for $i:=0;$i<$n; $i++ do
if grid.cell(np,$i)=0 then
return($i+1+#32+grid.cell(f,$i)+#32);
endif;
next;
return('-');
end

Dynamically calculated column expression to return a numeric value, from the Custom 1 field, affected by a percentage value gathered from Custom 2 field

C1*(1+C2/100)

Dynamically calculated column expression to return the number of days between the file modification and creation dates.

DaysBetween(date(md),date(cd))

Dynamically calculated column expression to return the file extension. Useful to sort by file type (zip, rar, pdf, chm, ...)

begin
var 'i','s' end;
$s:=an;
if $s='' then
$s:=f;
endif;
$i:=pos('.',reversestr($s));
if $i>0 then
return(lowercase(rightstr($s,$i-1)));
else
return('');
endd;
end