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

2 Likes