ExifTool Custom Columns

This script add-in generates custom columns showing metadata provided by ExifTool.

It's designed for speed and comes with a few helper buttons that make it convenient and easy to use. The custom columns can be formatted as dates and numbers which makes sorting, grouping, renaming etc. much more powerful.

JScript
var cmd = DOpus.Create().Command();
var fsu = DOpus.FSUtil();
var fso = new ActiveXObject('Scripting.FileSystemObject');
var wsh = new ActiveXObject('WScript.Shell');
var exifTags = DOpus.Create().Map();

var exeExifTool = fsu.Resolve('/bin\\exiftool\\exiftool.exe'); // -- Adjust to your system
var cacheFolder = fsu.Resolve('/profile\\ExifToolCache'); // -- Adjust to your preferences
var maxCacheAge = 60; // Rebuild cache if older than ... minutes -- Adjust to your preferences
var log = true; // -- Adjust to your preferences. Set to false if you don't want any logging

// Column definitions go here. Make sure there is no comma in the last line before the closing bracket.
// group, tag: reference for ExifTool (mandatory)
// name, label, header: adjust to your preferences (optional)
// justify: like Opus standard for columns (optional)
// type: datetime, date, time, number. String, if left empty (optional)
// defaultValue: value, if no tag is found via ExifTool (optional)

// group, tag, name, label, header, defaultValue, justify, type
var exifColumns = [
    new DefineColumn('Canon', 'CanonExposureMode', '', '', '', '', '', ''),
    new DefineColumn('Canon', 'FocusMode', '', '', '', '', '', ''),
    new DefineColumn('Canon', 'MeteringMode', '', '', '', '', '', ''),
    new DefineColumn('Canon', 'NumAFPoints', '', '', '', '', '', 'number'),
    new DefineColumn('Canon', 'OneShotAFRelease', '', '', '', '', '', ''),
    new DefineColumn('Canon', 'ValidAFPoints', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'Aperture', '', '', '', '', '', 'number'),
    new DefineColumn('Composite', 'AvgBitrate', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'CircleOfConfusion', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'FOV', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'HyperfocalDistance', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'ImageSize', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'LensID', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'LightValue', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'Megapixels', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'Rotation', '', '', '', '', '', 'number'),
    new DefineColumn('Composite', 'ShutterSpeed', '', '', '', '', '', ''),
    new DefineColumn('Composite', 'SubSecCreateDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('Composite', 'SubSecDateTimeOriginal', 'SSDTO', 'SSDTO', 'SSDTO', '', '', 'datetime'),
    new DefineColumn('EXE', 'CompanyName', '', '', '', '', '', ''),
    new DefineColumn('EXE', 'MachineType', '', '', '', '', '', ''),
    new DefineColumn('EXE', 'SubsystemVersion', '', '', '', '', '', ''),
    new DefineColumn('EXE', 'TimeStamp', '', '', '', '', '', 'datetime'),
    new DefineColumn('EXIF', 'CreateDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('EXIF', 'DateTimeOriginal', '', '', '', '', '', 'datetime'),
    new DefineColumn('EXIF', 'Model', '', '', '', '', '', ''),
    new DefineColumn('EXIF', 'Orientation', '', '', '', '', '', ''),
    new DefineColumn('ExifIFD', 'DateTimeOriginal', '', '', '', '', '', 'datetime'),
    new DefineColumn('File', 'FileAccessDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('File', 'FileCreateDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('File', 'FileModifyDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('File', 'FileTypeExtension', '', '', '', '', '', ''),
    new DefineColumn('H264', 'ApertureSetting', '', '', '', '', '', ''),
    new DefineColumn('H264', 'DateTimeOriginal', 'DateMTS', 'DateMTS', 'DateMTS', '', '', 'datetime'),
    new DefineColumn('H264', 'ExposureProgram', '', '', '', '', '', ''),
    new DefineColumn('H264', 'ExposureTime', '', '', '', '', '', ''),
    new DefineColumn('H264', 'FNumber', '', '', '', '', '', 'number'),
    new DefineColumn('H264', 'Focus', '', '', '', '', '', ''),
    new DefineColumn('H264', 'Gain', '', '', '', '', '', ''),
    new DefineColumn('H264', 'ImageHeight', '', '', '', '', '', ''),
    new DefineColumn('H264', 'ImageStabilization', '', '', '', '', '', ''),
    new DefineColumn('H264', 'ImageWidth', '', '', '', '', '', ''),
    new DefineColumn('H264', 'Model', '', '', '', '', '', ''),
    new DefineColumn('M2TS', 'Duration', '', '', '', '', '', 'time'), 
    new DefineColumn('M2TS', 'VideoStreamType', '', '', '', '', '', ''),
    new DefineColumn('MakerNotes', 'CameraOrientation', '', '', '', '', '', ''),
    new DefineColumn('MakerNotes', 'ShutterCount', 'SSC', 'SSC', 'SSC', '', '', 'number'),
    new DefineColumn('Matroska', 'DateTimeOriginal', '', '', '', '', '', ''),
    new DefineColumn('Matroska', 'DisplayHeight', '', '', '', '', '', 'number'),
    new DefineColumn('Matroska', 'DisplayWidth', '', '', '', '', '', 'number'),
    new DefineColumn('Matroska', 'Duration', 'MatDur', '', '', '', '', 'time'),
    new DefineColumn('Matroska', 'ImageHeight', '', '', '', '', '', 'number'),
    new DefineColumn('Matroska', 'ImageWidth', '', '', '', '', '', 'number'),
    new DefineColumn('Matroska', 'TrackNumber', '', '', '', '', 'number', ''),
    new DefineColumn('PDF', 'CreateDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('PDF', 'Creator', '', '', '', '', '', ''),
    new DefineColumn('PDF', 'ModifyDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('PDF', 'PageCount', '', '', '', '', '', 'number'),
    new DefineColumn('PDF', 'Producer', '', '', '', '', '', ''),
    new DefineColumn('PDF', 'Title', '', '', '', 'Move on. Nothing to see here but the PDF default value', 'left', ''),
    new DefineColumn('QuickTime', 'AudioAvgBitrate', '', '', '', '', '', ''),
    new DefineColumn('QuickTime', 'CompressorID', '', '', '', '', '', ''),
    new DefineColumn('QuickTime', 'CreateDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('QuickTime', 'CreationDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('QuickTime', 'Duration', '', '', '', '', '', 'time'),
    new DefineColumn('QuickTime', 'MediaCreateDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('QuickTime', 'MediaDuration', '', '', '', '', '', 'time'),
    new DefineColumn('QuickTime', 'MediaModifyDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('QuickTime', 'Model', '', '', '', '', '', ''),
    new DefineColumn('QuickTime', 'ModifyDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('QuickTime', 'TrackCreateDate', '', '', '', '', '', ''),
    new DefineColumn('QuickTime', 'TrackModifyDate', '', '', '', '', '', ''),
    new DefineColumn('QuickTime', 'VideoAvgBitrate', '', '', '', '', '', ''),
    new DefineColumn('QuickTime', 'VideoAvgFrameRate', '', '', '', '', '', ''),
    new DefineColumn('QuickTime', 'VideoSize', '', '', '', '', '', ''),
    new DefineColumn('Sony', 'FocusMode', '', '', '', '', '', ''),
    new DefineColumn('XML', 'CreationDateValue', '', '', '', '', '', 'datetime'),
    new DefineColumn('XML', 'DeviceManufacturer', '', '', '', '', '', ''),
    new DefineColumn('XML', 'DeviceModelName', '', '', '', '', '', ''),
    new DefineColumn('XML', 'DeviceSerialNo', '', '', '', '', '', ''),
    new DefineColumn('XML', 'VideoFormatVideoFrameCaptureFps', '', '', '', '', '', ''),
    new DefineColumn('XMP', 'Contributor', '', '', '', '', '', ''),
    new DefineColumn('XMP', 'CreateDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('XMP', 'Creator', '', '', '', '', '', ''),
    new DefineColumn('XMP', 'CreatorTool', '', '', '', '', '', ''),
    new DefineColumn('XMP', 'Date', '', '', '', '', '', 'datetime'),
    new DefineColumn('XMP', 'DateCreated', '', '', '', '', '', 'datetime'),
    new DefineColumn('XMP', 'Description', '', '', '', '', '', ''),
    new DefineColumn('XMP', 'Format', '', '', '', '', '', ''),
    new DefineColumn('XMP', 'MetadataDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('XMP', 'ModifyDate', '', '', '', '', '', 'datetime'),
    new DefineColumn('XMP', 'Producer', '', '', '', '', '', ''),
    new DefineColumn('XMP', 'Title', '', '', '', '', 'left', ''),
    new DefineColumn('XMP', 'XMPToolkit', '', '', '', '', '', '')
];

function DefineColumn(group, tag, name, label, header, defaultValue, justify, type) {
    this.group = group;
    this.tag = tag;
    var tmp = (group + '-' + tag);
    this.name = name == '' ? tmp : name;
    this.label = label == '' ? tmp : label;
    this.header = header == '' ? tmp : header;
    this.defaultValue = defaultValue;
    this.justify = justify;
    this.type = type;
}

function OnInit(initData) {
    initData.name = 'ExifTool';
    initData.desc = 'Provide columns for tags read via exiftool.exe';
    initData.version = '2021-07-17';
    initData.url = 'https://resource.dopus.com';
    initData.default_enable = true;

    cmd.RunCommand('CreateFolder NAME="' + cacheFolder + '"');

    Log('exeExifTool: ' + exeExifTool + (fsu.Exists(exeExifTool) ? ' - OK' : ' - not found!'));
    Log('cacheFolder: ' + cacheFolder + (fsu.Exists(cacheFolder) ? ' - OK' : ' - not found!'));
}

function OnAddColumns(AddColData) {
    for (var i = 0; i < exifColumns.length; ++i) {
        var column = exifColumns[i];
        var col = AddColData.AddColumn();
        col.multicol = true;
        col.name = column.name;
        col.label = column.label;
        col.header = column.header;
        col.justify = column.justify;
        col.type = column.type;
        col.method = 'OnColumn';
    }
}

function OnColumn(scriptColData) {
    var item = scriptColData.item;
    if (item.is_dir) return;
    if (item.path.drive == 0) return;

    var cacheFile = fsu.GetItem(cacheFolder + '\\' + String(item.realpath).replace(':', '') + '.txt');

    var cutOffDate = DOpus.Create().Date();
    cutOffDate.Sub(maxCacheAge, 'm'); // Current date minus ... minutes

    if (!fsu.Exists(cacheFile) || fsu.GetItem(cacheFile.path).modify.Compare(cutOffDate) < 0) {
        Log('Processing ' + fso.GetFolder(item.path).files.count + ' files in "' + item.path + '" with ExifTool...');

        var cmdLine = '"' + exeExifTool + '" -short -duplicates -unknown -groupNames -tab -textOut! "' + cacheFile.path + '\\%f.%e.txt" -extension "*" "' + String(item.path).replace(/\\$/, '') + '"'; // ExifTool doesn't like the trailing slashes item.path produces for root folders like C:\
        wsh.Run(cmdLine, 0, true);
        cmd.RunCommand('SetAttr FILE="' + cacheFile.path + '" META "lastmodifieddate:' + DOpus.Create().Date().Format('D#yyyy-MM-dd T#HH:mm:ss') + '"');

        Log('... done!');
    }

    if (!fsu.Exists(cacheFile)) {
        Log('*** Error: cache file could not be created! ***');
        Log('item:      ' + item);
        Log('cacheFile: ' + cacheFile);
        Log('');
        Log('cmdLine:');
        Log(cmdLine);
        Log('');
        return;
    }

    exifTags.clear();

    var tf = fso.OpenTextFile(cacheFile, 1);
    while (!tf.AtEndOfStream) {
        var line = tf.ReadLine().split('\t');
        var group = line[0];
        var tag = line[1];
        var value = line[2];
        var key = group + '-' + tag;
        exifTags(key) = value;
    }
    tf.Close();

    for (var i = 0; i < exifColumns.length; ++i) {
        var column = exifColumns[i];
        var key = column.group + '-' + column.tag;
        var value = exifTags.exists(key) ? exifTags(key) : column.defaultValue;

        if (value != '') {
            if (column.type == 'datetime' || column.type == 'date' || column.type == 'time') {
                value = DOpus.Create().Date(value.replace(/:/g, ''));
            } else if (column.type == 'number') {
                value = Number(value);
            }
        }

        scriptColData.columns(column.name).value = value;
    }
}

function Log(str) {
    if (log) DOpus.Output(str);
}

How to install the script

  • Copy ColumnExifTool.js.txt to /scripts.
  • Place the helper buttons on a toolbar
  • Download exiftool.exe from www.exiftool.org and copy it to a convenient place
  • Adjust the path to exiftool.exe in ColumnExifTool.js and Generate Helper Files

How to use the add-in

The script already contains a selection of custom columns. They can be turned on and off via right-click in the column header Columns/Script/ExifTool. Or all at once with the button Toggle ExifTool (all).

Button
Set COLUMNSTOGGLE="scp:ExifTool/Canon-CanonExposureMode(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Canon-FocusMode(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Canon-MeteringMode(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Canon-NumAFPoints(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Canon-OneShotAFRelease(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Canon-ValidAFPoints(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-Aperture(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-AvgBitrate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-CircleOfConfusion(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-FOV(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-HyperfocalDistance(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-ImageSize(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-LensID(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-LightValue(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-Megapixels(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-Rotation(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-ShutterSpeed(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Composite-SubSecCreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/SSDTO(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXE-CompanyName(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXE-MachineType(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXE-SubsystemVersion(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXE-TimeStamp(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXIF-CreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXIF-DateTimeOriginal(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXIF-Model(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/EXIF-Orientation(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/ExifIFD-DateTimeOriginal(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/File-FileAccessDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/File-FileCreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/File-FileModifyDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/File-FileTypeExtension(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-ApertureSetting(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Date MTS(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-ExposureProgram(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-ExposureTime(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-FNumber(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-Focus(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-Gain(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-ImageHeight(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-ImageStabilization(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-ImageWidth(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/H264-Model(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/M2TS-Duration(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/M2TS-VideoStreamType(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/MakerNotes-CameraOrientation(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/SSC(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Matroska-DateTimeOriginal(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Matroska-DisplayHeight(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Matroska-DisplayWidth(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/MatDur(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Matroska-ImageHeight(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Matroska-ImageWidth(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Matroska-TrackNumber(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/PDF-CreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/PDF-Creator(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/PDF-ModifyDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/PDF-PageCount(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/PDF-Producer(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/PDF-Title(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-AudioAvgBitrate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-CompressorID(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-CreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-CreationDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-Duration(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-MediaCreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-MediaDuration(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-MediaModifyDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-Model(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-ModifyDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-TrackCreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-TrackModifyDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-VideoAvgBitrate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-VideoAvgFrameRate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/QuickTime-VideoSize(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/Sony-FocusMode(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XML-CreationDateValue(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XML-DeviceManufacturer(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XML-DeviceModelName(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XML-DeviceSerialNo(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XML-VideoFormatVideoFrameCaptureFps(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-Contributor(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-CreateDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-Creator(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-CreatorTool(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-Date(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-DateCreated(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-Description(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-Format(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-MetadataDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-ModifyDate(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-Producer(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-Title(!,a,0)"
Set COLUMNSTOGGLE="scp:ExifTool/XMP-XMPToolkit(!,a,0)"

Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" textcol="none">
	<label>Toggle ExifTool (all)</label>
	<icon1>#usercommand</icon1>
	<function type="normal">
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Canon-CanonExposureMode(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Canon-FocusMode(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Canon-MeteringMode(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Canon-NumAFPoints(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Canon-OneShotAFRelease(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Canon-ValidAFPoints(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-Aperture(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-AvgBitrate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-CircleOfConfusion(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-FOV(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-HyperfocalDistance(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-ImageSize(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-LensID(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-LightValue(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-Megapixels(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-Rotation(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-ShutterSpeed(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Composite-SubSecCreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/SSDTO(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXE-CompanyName(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXE-MachineType(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXE-SubsystemVersion(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXE-TimeStamp(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXIF-CreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXIF-DateTimeOriginal(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXIF-Model(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/EXIF-Orientation(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/ExifIFD-DateTimeOriginal(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/File-FileAccessDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/File-FileCreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/File-FileModifyDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/File-FileTypeExtension(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-ApertureSetting(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Date MTS(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-ExposureProgram(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-ExposureTime(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-FNumber(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-Focus(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-Gain(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-ImageHeight(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-ImageStabilization(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-ImageWidth(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/H264-Model(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/M2TS-Duration(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/M2TS-VideoStreamType(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/MakerNotes-CameraOrientation(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/SSC(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Matroska-DateTimeOriginal(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Matroska-DisplayHeight(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Matroska-DisplayWidth(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/MatDur(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Matroska-ImageHeight(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Matroska-ImageWidth(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Matroska-TrackNumber(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/PDF-CreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/PDF-Creator(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/PDF-ModifyDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/PDF-PageCount(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/PDF-Producer(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/PDF-Title(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-AudioAvgBitrate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-CompressorID(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-CreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-CreationDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-Duration(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-MediaCreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-MediaDuration(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-MediaModifyDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-Model(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-ModifyDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-TrackCreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-TrackModifyDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-VideoAvgBitrate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-VideoAvgFrameRate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/QuickTime-VideoSize(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/Sony-FocusMode(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XML-CreationDateValue(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XML-DeviceManufacturer(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XML-DeviceModelName(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XML-DeviceSerialNo(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XML-VideoFormatVideoFrameCaptureFps(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-Contributor(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-CreateDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-Creator(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-CreatorTool(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-Date(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-DateCreated(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-Description(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-Format(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-MetadataDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-ModifyDate(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-Producer(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-Title(!,a,0)&quot;</instruction>
		<instruction>Set COLUMNSTOGGLE=&quot;scp:ExifTool/XMP-XMPToolkit(!,a,0)&quot;</instruction>
	</function>
</button>

How to get your own columns

Select the files whose metadata interests you and run Generate Helper Files on them. The button will create three text files per selected file:

<filename>-ColCmds.txt
<filename>-ColDefs.txt
<filename>-Tags.txt

ColDefs contains the column definitions for all available metadata. It provides the real values as a comment for easier selection. Pick the ones you like and copy them into ColumnExifTool.js. I usually remove the comments, but that's optional.

ColCmds contains the commands for a button that will toggle the new custom columns. Pick the ones you need and copy them into a button. Run the button and enjoy your new columns.

Tags is the base for the two other files. Can be recycled e.g. for diffing.

These three files can be deleted once you copied all the info you need.

JScript
// version: 2021-07-17

function OnClick(clickData) {
    var cmd = clickData.func.command;
    var tab = clickData.func.sourcetab;
    var dlg = clickData.func.Dlg();
    var wsh = new ActiveXObject('WScript.Shell');
    var fso = new ActiveXObject('Scripting.FileSystemObject');
    var fsu = DOpus.FSUtil();
    var exeExifTool = fsu.Resolve('/bin\\exiftool\\exiftool.exe');

    cmd.deselect = false;

    if (!fsu.Exists(exeExifTool)) {
        dlg.Request('exiftool.exe not found!', 'OK');
        return;
    }

    cmd.RunCommand('Set UTILITY=otherlog');
    DOpus.ClearOutput();
    DOpus.Output('Enumerating...\n');

    for (var e = new Enumerator(tab.selected_files); !e.atEnd(); e.moveNext()) {
        var item = e.item();
        DOpus.Output(item);

        var fileTags = fsu.GetItem(item + '-Tags.txt');

        var cmdLine = '"' + exeExifTool + '" -short -duplicates -unknown -groupNames -tab -textOut! "%0f' + fileTags + '" "' + item + '"';
        wsh.Run(cmdLine, 0, true);

        var tfColDefs = fso.CreateTextFile(item + '-ColDefs.txt');
        var tfColCmds = fso.CreateTextFile(item + '-ColCmds.txt');

        var tf = fso.OpenTextFile(fileTags, 1);
        while (!tf.AtEndOfStream) {
            var line = tf.ReadLine().split('\t');
            var group = line[0];
            var tag = line[1];
            var value = line[2];
            var str = 'new DefineColumn(\'' + group + '\', \'' + tag + '\', \'\', \'\', \'\', \'\', \'\', \'\'),';
            while (str.length < 120) str += ' ';
            str += '// ' + value;
            tfColDefs.WriteLine(str);
            tfColCmds.WriteLine('Set COLUMNSTOGGLE="scp:ExifTool/' + group + '-' + tag + '(!,a,0)"');
        }
        tf.Close();

        tfColDefs.Close();
        tfColCmds.Close();
    }
    DOpus.Output('\n... done');
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" textcol="none">
	<label>Generate Helper Files</label>
	<tip>Generates .txt helper files for selected files</tip>
	<icon1>#newcommand</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>// version: 2021-07-17</instruction>
		<instruction />
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    var tab = clickData.func.sourcetab;</instruction>
		<instruction>    var dlg = clickData.func.Dlg();</instruction>
		<instruction>    var wsh = new ActiveXObject(&apos;WScript.Shell&apos;);</instruction>
		<instruction>    var fso = new ActiveXObject(&apos;Scripting.FileSystemObject&apos;);</instruction>
		<instruction>    var fsu = DOpus.FSUtil();</instruction>
		<instruction>    var exeExifTool = fsu.Resolve(&apos;/bin\\exiftool\\exiftool.exe&apos;);</instruction>
		<instruction />
		<instruction>    cmd.deselect = false;</instruction>
		<instruction />
		<instruction>    if (!fsu.Exists(exeExifTool)) {</instruction>
		<instruction>        dlg.Request(&apos;exiftool.exe not found!&apos;, &apos;OK&apos;);</instruction>
		<instruction>        return;</instruction>
		<instruction>    }</instruction>
		<instruction />
		<instruction>    cmd.RunCommand(&apos;Set UTILITY=otherlog&apos;);</instruction>
		<instruction>    DOpus.ClearOutput();</instruction>
		<instruction>    DOpus.Output(&apos;Enumerating...\n&apos;);</instruction>
		<instruction />
		<instruction>    for (var e = new Enumerator(tab.selected_files); !e.atEnd(); e.moveNext()) {</instruction>
		<instruction>        var item = e.item();</instruction>
		<instruction>        DOpus.Output(item);</instruction>
		<instruction />
		<instruction>        var fileTags = fsu.GetItem(item + &apos;-Tags.txt&apos;);</instruction>
		<instruction />
		<instruction>        var cmdLine = &apos;&quot;&apos; + exeExifTool + &apos;&quot; -short -duplicates -unknown -groupNames -tab -textOut! &quot;%0f&apos; + fileTags + &apos;&quot; &quot;&apos; + item + &apos;&quot;&apos;;</instruction>
		<instruction>        wsh.Run(cmdLine, 0, true);</instruction>
		<instruction />
		<instruction>        var tfColDefs = fso.CreateTextFile(item + &apos;-ColDefs.txt&apos;);</instruction>
		<instruction>        var tfColCmds = fso.CreateTextFile(item + &apos;-ColCmds.txt&apos;);</instruction>
		<instruction />
		<instruction>        var tf = fso.OpenTextFile(fileTags, 1);</instruction>
		<instruction>        while (!tf.AtEndOfStream) {</instruction>
		<instruction>            var line = tf.ReadLine().split(&apos;\t&apos;);</instruction>
		<instruction>            var group = line[0];</instruction>
		<instruction>            var tag = line[1];</instruction>
		<instruction>            var value = line[2];</instruction>
		<instruction>            var str = &apos;new DefineColumn(\&apos;&apos; + group + &apos;\&apos;, \&apos;&apos; + tag + &apos;\&apos;, \&apos;\&apos;, \&apos;\&apos;, \&apos;\&apos;, \&apos;\&apos;, \&apos;\&apos;, \&apos;\&apos;),&apos;;</instruction>
		<instruction>            while (str.length &lt; 120) str += &apos; &apos;;</instruction>
		<instruction>            str += &apos;// &apos; + value;</instruction>
		<instruction>            tfColDefs.WriteLine(str);</instruction>
		<instruction>            tfColCmds.WriteLine(&apos;Set COLUMNSTOGGLE=&quot;scp:ExifTool/&apos; + group + &apos;-&apos; + tag + &apos;(!,a,0)&quot;&apos;);</instruction>
		<instruction>        }</instruction>
		<instruction>        tf.Close();</instruction>
		<instruction />
		<instruction>        tfColDefs.Close();</instruction>
		<instruction>        tfColCmds.Close();</instruction>
		<instruction>    }</instruction>
		<instruction>    DOpus.Output(&apos;\n... done&apos;);</instruction>
		<instruction>}</instruction>
	</function>
</button>

Adjusting the columns to your need

The columns' standard name is a combination of the metadata's group and tag name. It's often quite long, so you can change the Opus name, label, and header to something shorter in the new DefineColumn(... lines in the script.

You can also provide a default value, the justificaton, and the type. Most important is probably the type datetime for metadata that represents a date. The script has some examples built-in.

Helper button: Auto-Size All Columns

Existing columns that are set to 'collapse' might shrink too much when there are many new columns. This button sets all columns' widths to 'auto'.

JScript
// version: 2021-07-17

function OnClick(clickData) {
    var cmd = clickData.func.command;
    var tab = clickData.func.sourcetab;
    cmd.deselect = false;

    var cmdLine = 'Set COLUMNSADD=';
	
    for (var e = new Enumerator(tab.format.columns); !e.atEnd(); e.moveNext()) {
        var col = e.item();
        cmdLine += '"' + col.name + '(!,a,0)",';
    }

	cmdLine = cmdLine.substring(0, cmdLine.length - 1);
    cmd.RunCommand(cmdLine);
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" separate="yes" textcol="none">
	<label>Auto-Size All Columns </label>
	<tip>All columns&apos; size will be set to &apos;auto&apos;</tip>
	<icon1>#newcommand</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>// version: 2021-07-17</instruction>
		<instruction />
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    var tab = clickData.func.sourcetab;</instruction>
		<instruction>    cmd.deselect = false;</instruction>
		<instruction />
		<instruction>    var cmdLine = &apos;Set COLUMNSADD=&apos;;</instruction>
		<instruction>	</instruction>
		<instruction>    for (var e = new Enumerator(tab.format.columns); !e.atEnd(); e.moveNext()) {</instruction>
		<instruction>        var col = e.item();</instruction>
		<instruction>        cmdLine += &apos;&quot;&apos; + col.name + &apos;(!,a,0)&quot;,&apos;;</instruction>
		<instruction>    }</instruction>
		<instruction />
		<instruction>    cmdLine = cmdLine.substring(0, cmdLine.length - 1);</instruction>
		<instruction>    cmd.RunCommand(cmdLine);</instruction>
		<instruction>}</instruction>
	</function>
</button>

Helper button: Open ExifToolCache in Dest

This button opens the cache folder in the destination and selects the files that correspond with the selection in the source. Helpful for debugging, diffing, cache cleaning.

JScript
// version: 2021-07-17

function OnClick(clickData) {
    var cmd = clickData.func.command;
    var tab = clickData.func.sourcetab;
    var fsu = DOpus.FSUtil();
    var lst = DOpus.listers.lastactive;
    cmd.deselect = false;

    var cacheFolder = fsu.Resolve('/profile\\ExifToolCache');
    
    var srcPath = String(tab.path);
    if (srcPath.substring(0, 2) == '::') return;

    var destPath = cacheFolder + '\\' + srcPath.replace(':', '');
    cmd.RunCommand('CreateFolder NAME="' + destPath + '"');
    cmd.RunCommand('GO PATH="' + destPath + '" NEWTAB=findexisting OPENINDUAL');
    
    cmd.ClearFiles();
    for (var e = new Enumerator(tab.selected_files); !e.atEnd(); e.moveNext()) {
        var item = e.item();
        cmd.AddFile(destPath + '\\' + item.name + '.txt');
    }
    cmd.SetSourceTab(lst.desttab);
    cmd.RunCommand('SELECT NONE');
    cmd.RunCommand('SELECT FROMSCRIPT SETFOCUS');
    cmd.RunCommand('SELECT SHOWFOCUS');
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" textcol="none">
	<label>Open ExifToolCache in Dest</label>
	<tip>Opens cache folder and selects corresponding files</tip>
	<icon1>#newcommand</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>// version: 2021-07-17</instruction>
		<instruction />
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    var tab = clickData.func.sourcetab;</instruction>
		<instruction>    var fsu = DOpus.FSUtil();</instruction>
		<instruction>    var lst = DOpus.listers.lastactive;</instruction>
		<instruction>    cmd.deselect = false;</instruction>
		<instruction />
		<instruction>    var cacheFolder = fsu.Resolve(&apos;/profile\\ExifToolCache&apos;);</instruction>
		<instruction>    </instruction>
		<instruction>    var srcPath = String(tab.path);</instruction>
		<instruction>    if (srcPath.substring(0, 2) == &apos;::&apos;) return;</instruction>
		<instruction />
		<instruction>    var destPath = cacheFolder + &apos;\\&apos; + srcPath.replace(&apos;:&apos;, &apos;&apos;);</instruction>
		<instruction>    cmd.RunCommand(&apos;CreateFolder NAME=&quot;&apos; + destPath + &apos;&quot;&apos;);</instruction>
		<instruction>    cmd.RunCommand(&apos;GO PATH=&quot;&apos; + destPath + &apos;&quot; NEWTAB=findexisting OPENINDUAL&apos;);</instruction>
		<instruction>    </instruction>
		<instruction>    cmd.ClearFiles();</instruction>
		<instruction>    for (var e = new Enumerator(tab.selected_files); !e.atEnd(); e.moveNext()) {</instruction>
		<instruction>        var item = e.item();</instruction>
		<instruction>        cmd.AddFile(destPath + &apos;\\&apos; + item.name + &apos;.txt&apos;);</instruction>
		<instruction>    }</instruction>
		<instruction>    cmd.SetSourceTab(lst.desttab);</instruction>
		<instruction>    cmd.RunCommand(&apos;SELECT NONE&apos;);</instruction>
		<instruction>    cmd.RunCommand(&apos;SELECT FROMSCRIPT SETFOCUS&apos;);</instruction>
		<instruction>    cmd.RunCommand(&apos;SELECT SHOWFOCUS&apos;);</instruction>
		<instruction>}</instruction>
	</function>
</button>

Helper button: Columns To Commands

This button modifies the clipboard content. It converts column definitions to Set commands. Just select all the new DefineColumn(... lines in the script you need, copy them to the clipboard, hit the button, and paste the clipboard content to the Opus toggle column button.

JScript
// version: 2021-07-17

function OnClick(clickData) {
    if (DOpus.GetClipFormat() != 'text') return;

    var cmd = clickData.func.command;
    cmd.deselect = false;
    cmd.RunCommand('Set UTILITY=otherlog');
    DOpus.ClearOutput();

    var tmp = '';
    var clipLines = DOpus.GetClip().split('\r\n');

    for (var i = 0; i < clipLines.length; ++i) {
        var line = clipLines[i].split('\'');
        var group = line[1];
        var tag = line[3];
        var name = line[5];
        if (name == '') name = group + '-' + tag;
        if (typeof name == 'undefined') continue;
        tmp += 'Set COLUMNSTOGGLE="scp:ExifTool/' + name + '(!,a,0)"' + '\n';
    }
  
    DOpus.Output(tmp);
    DOpus.SetClip(tmp);
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" textcol="none">
	<label>Columns To Commands</label>
	<tip>Modifies clipboard content: convert column definitions to Set commands</tip>
	<icon1>#clipcopy</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>// version: 2021-07-17</instruction>
		<instruction />
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    if (DOpus.GetClipFormat() != &apos;text&apos;) return;</instruction>
		<instruction />
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    cmd.deselect = false;</instruction>
		<instruction>    cmd.RunCommand(&apos;Set UTILITY=otherlog&apos;);</instruction>
		<instruction>    DOpus.ClearOutput();</instruction>
		<instruction />
		<instruction>    var tmp = &apos;&apos;;</instruction>
		<instruction>    var clipLines = DOpus.GetClip().split(&apos;\r\n&apos;);</instruction>
		<instruction />
		<instruction>    for (var i = 0; i &lt; clipLines.length; ++i) {</instruction>
		<instruction>        var line = clipLines[i].split(&apos;\&apos;&apos;);</instruction>
		<instruction>        var group = line[1];</instruction>
		<instruction>        var tag = line[3];</instruction>
		<instruction>        var name = line[5];</instruction>
		<instruction>        if (name == &apos;&apos;) name = group + &apos;-&apos; + tag;</instruction>
		<instruction>        if (typeof name == &apos;undefined&apos;) continue;</instruction>
		<instruction>        tmp += &apos;Set COLUMNSTOGGLE=&quot;scp:ExifTool/&apos; + name + &apos;(!,a,0)&quot;&apos; + &apos;\n&apos;;</instruction>
		<instruction>    }</instruction>
		<instruction>  </instruction>
		<instruction>    DOpus.Output(tmp);</instruction>
		<instruction>    DOpus.SetClip(tmp);</instruction>
		<instruction>}</instruction>
	</function>
</button>

Helper button: Delete ExifToolCache

This button deletes the cache folder for the source and refreshes the file display. Useful, if you need to force a rebuilt of the cache, because the script could not detect a change in the files.

JScript
// version: 2021-10-14

function OnClick(clickData) {
    var cmd = clickData.func.command;
    var tab = clickData.func.sourcetab;
    var fsu = DOpus.FSUtil();
    cmd.deselect = false;

    var cacheFolder = fsu.Resolve('/profile\\ExifToolCache');

    var srcPath = String(tab.path);
    if (srcPath.substring(0, 2) == '::') return;

    var destPath = cacheFolder + '\\' + srcPath.replace(':', '');

    cmd.RunCommand('Delete FILE="' + destPath + '" QUIET');
    cmd.RunCommand('Go REFRESH');
}
Button as XML
<?xml version="1.0"?>
<button backcol="none" display="both" label_pos="right" textcol="none">
	<label>Delete ExifToolCache</label>
	<tip>Deletes corresponding folder in ExifToolCache and refreshes the lister</tip>
	<icon1>#newcommand</icon1>
	<function type="script">
		<instruction>@script JScript</instruction>
		<instruction>// version: 2021-10-14</instruction>
		<instruction />
		<instruction>function OnClick(clickData) {</instruction>
		<instruction>    var cmd = clickData.func.command;</instruction>
		<instruction>    var tab = clickData.func.sourcetab;</instruction>
		<instruction>    var fsu = DOpus.FSUtil();</instruction>
		<instruction>    cmd.deselect = false;</instruction>
		<instruction />
		<instruction>    var cacheFolder = fsu.Resolve(&apos;/profile\\ExifToolCache&apos;);</instruction>
		<instruction />
		<instruction>    var srcPath = String(tab.path);</instruction>
		<instruction>    if (srcPath.substring(0, 2) == &apos;::&apos;) return;</instruction>
		<instruction />
		<instruction>    var destPath = cacheFolder + &apos;\\&apos; + srcPath.replace(&apos;:&apos;, &apos;&apos;);</instruction>
		<instruction />
		<instruction>    cmd.RunCommand(&apos;Delete FILE=&quot;&apos; + destPath + &apos;&quot;&apos;); // QUIET</instruction>
		<instruction>    cmd.RunCommand(&apos;Go REFRESH&apos;);</instruction>
		<instruction>}</instruction>
	</function>
</button>

Good to know

  • The script is inspired by @tbone's Extended EXIF.
  • Why ExifTool? ExifTool is THE tool when it comes to handling metadata. It reads and writes almost any tag and is not limited to images as the name might imply. You'll find many threads about it here in the forum and everything else at www.exiftool.org.
  • The script logs some info. Logging is minimal and shouldn't decrease performance, but you can turn it off.
  • The metadata is cached in /profile\ExifToolCache. Feel free to change the path.
  • Except for the cache the script writes nothing to your system.
  • The cache gets built, if the needed files don't exist and refreshed, when it is older than one hour. Time can be adjusted in the script.
  • The cache is always generated for an entire folder, so you might see a delay when accessing folders with many files.
  • Having many custom columns will not impact performance.
  • The script is not aware of file renames. If FileA gets renamed to FileB and metadata for a FileB is already in the cache, you'll see the wrong metadata.
  • The script can help Opus rename files, but it cannot change file metadata. You need ExifTool for this job.
  • ExifTool reads the tags in XML files as metadata. Cool, if you have always wanted to analyse the scheduled tasks on your system. A bit problematic, if you have it read the GPX files from your GPS logger. The cache files will have an enormous size, because every single coordinate will be turned into a column. Just sayin' :wink:

Change log

  • 2021-07-17: Initial Release
  • 2021-10-14: Added Helper button Delete ExifToolCache

How to use buttons and scripts from this forum

5 Likes

(Work in progress: Tutorial coming...)

This is a really useful tool - once you are familiar with the ExifTool commands.

Here is a related button, to update the PDF file-dates from the XML data;
exiftool -progress -m -P "-FileCreateDate<CreateDate" "-FileModifyDate<ModifyDate" {f}

And the inverse, to embed a new date from file-date, into XML & PDF dates within the Acrobat.PDF
exiftool -progress -m -P "-CreateDate<FileCreateDate" "-ModifyDate<FileModifyDate" *.pdf
(note we use the generic -CreateDate tag, rather than -xml:CreateDate, so both xml and pdf dates are set)
// -m Ignore minor errors and warnings
// -P Preserve file modification date/time
// -progress Show file progress count
// -delete_original Delete "_original" backups
DOpus button attached.
adjust PDF fileDates.dcf (591 Bytes)

I have the Exiftool file on my Desktop. I use Exiftool already with a couple of other applications. I have tried editing the path to exiftool.exe in the ColumnExifTool.js file and have not succeeded. No matter how I enter the path, I get an error 'Exiftool not found', and/or a message saying there is an error on line 170, position 9. I have been trying to get this to work for 3 hours.
Also, I can't figure out how to 'Generate Helper Files'.
Can somebody please help?

If you show us your edit, and the path to ExifTool on your system, we might be able to see what's wrong.

Did you double the backslashes? Opus can help with this:

Leo,
I finally got it right. I did not show it because I tried 20 or more variations. I don't know whether to include 'C:' since no Drive is listed in the original/unedited js.txt file.

Ixp tried to help, but copying the path with backslashes is still not how the path needs to be entered.
Thank you

Thank you for trying to help. However I can't insert the path as copied. I finally got it right after trying many variations.
I changed the copied path: ‘C:\Users\myusername\Desktop\exiftool.exe’
To: ‘/Users\myusername\Desktop\exiftool.exe’

I am using your ExifTool Custom Columns script. I have added an Exif DateTimeOriginal (EDTO) column to my customized Images Folder Format. If a photo does not have an EDTO, I use Exiftool to add one. However, when I return to DOPUs, no date appears in the EDTO column even If I refresh. The only way to get the newly added EDTO to appear in the column is to re-start my PC.
Can you or anyone else help me fix this?

The script uses a cache for the metadata. This cache gets rebuilt after one hour. If you change metadata and want to see the new values immediately in the columns, simply force a rebuilt by deleting the cache. The initial posting contains a button to do this.

Thank you for your help.
I have no programming experience, but I was able to get your script running after lots of trial and error.
I did not ‘Generate Helper Files’, as I have no idea what that means or how I would go about that.
I use a lot of programs that handle metadata, and changes I make are always reflected immediately. I appreciate your script, but it is disappointing to have to delete the cache for the new metadata to be shown.
Do you have any idea why the script is not detecting a change in the files?
I will try to set up the button to delete the cache.

The script could do a bit more record keeping to detect changes, but all you would get in return would be the ability to use the standard Refresh- instead of the Delete-Cache-And-Refresh-button, which you would still need to use if the metadata got changed by software that doesn't leave visible traces.

For the given mix of 3rd-party tool, ExifTool, and an Opus-script, this is as good as it gets, I think. But maybe there's a trick I am not aware of? Bring it on! I use the script every day myself, so I am very open to new ideas :slight_smile:

lxp,
Thank you for both your comment and your scripting work. I started using your script because of the problems/inconsistencies with the DOpus Date Taken field. My goal was to display the Exif DateTimeOriginal field in order to verify photo dates since I can't rely on the DOpus Date Taken field. For now, I will keep using ExiftoolGUI for this purpose.
Many applications display Exif DateTimeOriginal, so perhaps DOpus will add this field.

I am constantly refreshing DOpus, but I do not know why that is necessary. I never have to do that with other applications. If I did not have to refresh to see changes in ExifTool Custom Columns field, it would be much more appealing to me.

I'd be interested in knowing what tasks you use your script for. I've always got new ideas, but without context, I'm not sure what would be useful to you. I use a variety of different application to view, add, edit, and move photo metadata. Since I own or subscribe to so many applications for both Mac and PC, I pick the best application for whatever task I want to do. For example, if there is a need to save each file's original filename prior to batch renaming, I use Photo Mechanic to move the filename to a field such as Title (if Title is not being used) and rename and place the files into whatever folder structure I want all at the same time.

It shouldn't be needed unless something is caching data (e.g. this script, which is outside our control in general), or something is breaking change notifications (there's a FAQ on that).

Leo,
I've always had to refresh (F5) even before using this script. I need to keep careful track of all my clients' files, and so the Folder Formats I have configured always include columns for the number of files and the number of sub-folders. I frequently move files, move folders, and merge folders. The number of files, the number of folders, and the folder size does not change until I refresh.
I refresh so often I am no longer paying attention to what else refreshes (or needs to be refreshed).
By the way, the ability to set columns for the number of files and folder is one of my favourite things about DOpus.

The sub-file/folder counts aren't refreshed automatically (Windows has no good way to do that, but we're thinking of adding options to recalculate the counts more often; not sure exactly how that will work yet). Had that detail been included I would've mentioned that, but I assumed we were talking about photo metadata, given the thread.

This is really off-topic for this thread now.

Leo, it was my mistake to assume that there was some connection between the F5 refresh I do so often and the refresh needed for the ExifTool Custom Columns plugin. Sorry. Shall I delete those specific comments?