Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

unable to make script work CSV extraction

New Here ,
Jul 02, 2025 Jul 02, 2025
So I have a jsx script, and I want jsx script to be able to extract data from the CSV. 
CSV file is the same one I use when I data merge - my script is supposed to sun after datamerge and attach links to pictures.
- problem is that it gives me an issue.

error-indesign.JPG

 

´

// ---- (1) Language selection dialog: Let user pick language code for links ----
function chooseLanguage() {
    var languageCodes = ["da", "en", "sv"];
    var languages     = ["Dansk", "English", "Swedish"];
    var w = new Window("dialog", "Vælg sprog til links");
    w.orientation = "column";
    w.alignChildren = "left";
    w.add("statictext", undefined, "Vælg sprog til hyperlinks:");
    var dropdown = w.add("dropdownlist", undefined, languages);
    dropdown.selection = 0;
    w.add("button", undefined, "OK");
    w.add("button", undefined, "Annuller");
    if (w.show() !== 1) return null; // Cancelled
    return languageCodes[dropdown.selection.index];
}

 

// ---- (2) Ask user for CSV used for Data Merge, explain consequences ----
function chooseCSVFile() {
    var csvFile = File.openDialog(
        "Vælg den samme CSV-fil med billeddata, som du brugte i Data Merge (*.csv).\n\nDet er vigtigt at vælge den IDENTISKE fil for at links bliver korrekte.",
        "*.csv",
        false
    );
    if (!csvFile || !csvFile.exists) {
        alert("Ingen fil valgt, eller filen findes ikke.\n\nHusk: Du SKAL vælge den samme CSV, som blev brugt til Data Merge.");
        return null;
    }
    csvFile.open("r");
    var fileContents = csvFile.read();
    csvFile.close();
    return fileContents;
}

 

// ---- (3) Parse CSV: returns mapping imageBasename --> URL ----
function parseCSVToLinkData(csvText) {
    var billedLinkData = {};
    var lines = csvText.split(/\r?\n/);
    if (lines.length < 2) {
        alert("CSV filen indeholder ikke nok data.");
        return null;
    }
    var header = lines[0].split(";");
    var idxImg = header.indexOf("@BILLEDE");
    var idxUrl = header.indexOf("HYPERLINK");
    if (idxImg === -1 || idxUrl === -1) {
        alert("CSV header mangler en eller begge af følgende kolonner: HYPERLINK, @BILLEDE");
        return null;
    }
    for (var l = 1; l < lines.length; l++) {
        var line = lines[l];
        if (!line.trim()) continue; // skip empty
        var cols = line.split(";");
        if (cols.length <= Math.max(idxImg, idxUrl)) continue; // skip malformed
        var imgPath = cols[idxImg];
        var url     = cols[idxUrl];
        if (!imgPath || !url) continue; // skip incomplete
        var imgName = File(imgPath).name.toLowerCase().trim(); // just the filename, eg 0013474.jpg
        billedLinkData[imgName] = url;
    }
    return billedLinkData;
}

 

// ---- (4) Scan all rectangles on all pages for image or name match ----
function scanRectangles(doc, linkData) {
    var totalRectangles = 0, matchedRectangles = 0;
    var matchList = [], notMatchedList = [], matchedItems = [];
    for (var p = 0; p < doc.pages.length; p++) {
        var page = doc.pages[p];
        for (var i = 0; i < page.allPageItems.length; i++) {
            var item = page.allPageItems[i];
            if (item.constructor.name === "Rectangle") {
                totalRectangles++;
                var key = null;
                if (item.images && item.images.length > 0 && item.images[0].itemLink != null) {
                    key = item.images[0].itemLink.name.toLowerCase().trim();
                } else if (item.name && item.name.length > 0) {
                    key = item.name.toLowerCase().trim();
                }
                if (key && linkData.hasOwnProperty(key)) {
                    matchedRectangles++;
                    matchList.push(key);
                    matchedItems.push({rect: item, key: key, url: linkData[key]});
                } else {
                    notMatchedList.push(item.name || "<uden navn>");
                }
            }
        }
    }
    return {
        total: totalRectangles,
        matched: matchedRectangles,
        matchList: matchList,
        notMatchedList: notMatchedList,
        matchedItems: matchedItems
    };
}

 

// ---- (5) Show long text in a scrollable, resizable ScriptUI dialog ----
function showScrollableDialog(title, content) {
    var win = new Window("dialog", title);
    win.orientation = "column";
    win.alignChildren = "fill";
    var editText = win.add("edittext", undefined, content, {multiline: true, scrolling: true});
    editText.minimumSize.height = 300;
    editText.minimumSize.width  = 600;
    var btnGroup = win.add("group");
    btnGroup.alignment = "right";
    btnGroup.add("button", undefined, "OK");
    win.show();
}

 

// ---- (6) Add overlays + hyperlinks for all matched rectangles ----
function addHyperlinks(doc, scanResults) {
    var attachedLinks = [];
    for (var i = 0; i < scanResults.matchedItems.length; i++) {
        var item = scanResults.matchedItems[i].rect;
        var key = scanResults.matchedItems[i].key;
        var url = scanResults.matchedItems[i].url;
        try {
            var overlay = item.parentPage.rectangles.add({
                geometricBounds: item.geometricBounds,
                fillColor: doc.swatches.itemByName("None"),
                strokeColor: doc.swatches.itemByName("None"),
                layer: item.itemLayer
            });
            overlay.sendToBack();
            overlay.transparencySettings.blendingSettings.opacity = 0;
            var dest;
            try {
                dest = doc.hyperlinkURLDestinations.itemByName(url);
                if (!dest.isValid) throw "invalid";
            } catch (_) {
                dest = doc.hyperlinkURLDestinations.add(url, {name: url});
            }
            var source = doc.hyperlinkPageItemSources.add(overlay, {hidden: false});
            doc.hyperlinks.add(source, dest);
            attachedLinks.push(key + " -> " + url);
        } catch (e) {
            $.writeln("Fejl: " + e.message);
        }
    }
    return attachedLinks;
}

 

// ==== Main routine ====

 

if (!app.documents.length) {
    alert("Åbn et InDesign-dokument først.");
    exit();
}

 

var langCode = chooseLanguage();
if (!langCode) exit();

 

var csvText = chooseCSVFile();
if (!csvText) exit();

 

var linkData = parseCSVToLinkData(csvText);
if (!linkData) exit();

 

var doc = app.activeDocument;
var scanResults = scanRectangles(doc, linkData);

 

var diagMsg =
    "Diagnostik før processeringen:\n\n" +
    "Der er " + scanResults.total + " rektangler i dokumentet.\n" +
    scanResults.matched + " af dem matcher rapporten og vil få overlay og hyperlink.\n" +
    (scanResults.matched > 0
        ? ("\nFørste 10 matchede:\n" + scanResults.matchList.slice(0, 10).join("\n")) : "") +
    (scanResults.notMatchedList.length > 0
        ? ("\n\nRektangler IKKE i rapporten (første 10):\n" +
            scanResults.notMatchedList.slice(0,10).join("\n"))
        : "");

 

showScrollableDialog("Diagnostik", diagMsg);

 

var attachedLinks = addHyperlinks(doc, scanResults);

 

if (attachedLinks.length > 0) {
    var msg =
        attachedLinks.length + " hyperlinks blev tilføjet til rektangler:\n\n" +
        attachedLinks.join("\n");
    showScrollableDialog("Hyperlinks tilføjet", msg);
} else {
    showScrollableDialog("Hyperlinks tilføjet", "Ingen hyperlinks blev tilføjet.");
TOPICS
Scripting
136
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jul 02, 2025 Jul 02, 2025

You are using a method of Array that ExtendScript doesn't natively have: indexOf

 

Put this polyfill into your code, before calling indexOf:

if (!Array.prototype.indexOf) Array.prototype.indexOf = (function (Object, max, min) {
    "use strict";

    return function indexOf(member, fromIndex) {

        if (
            this === null
            || this === undefined
        )
            throw TypeError("Array.prototype.indexOf called on null or undefined");

        var that = Object(this),
  
...
Translate
Community Expert ,
Jul 02, 2025 Jul 02, 2025

You are using a method of Array that ExtendScript doesn't natively have: indexOf

 

Put this polyfill into your code, before calling indexOf:

if (!Array.prototype.indexOf) Array.prototype.indexOf = (function (Object, max, min) {
    "use strict";

    return function indexOf(member, fromIndex) {

        if (
            this === null
            || this === undefined
        )
            throw TypeError("Array.prototype.indexOf called on null or undefined");

        var that = Object(this),
            Len = that.length >>> 0,
            i = min(fromIndex | 0, Len);

        if (i < 0) i = max(0, Len + i);
        else if (i >= Len) return -1;

        if (member === void 0) {
            for (; i !== Len; ++i)
                if (that[i] === void 0 && i in that)
                    return i; // undefined
        } else if (member !== member) {
            for (; i !== Len; ++i)
                if (that[i] !== that[i])
                    return i; // NaN
        } else for (; i !== Len; ++i)
            if (that[i] === member)
                return i; // all else

        return -1; // if the value was not found, then return -1

    };
})(Object, Math.max, Math.min);
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 02, 2025 Jul 02, 2025

thanks @m1b  - do you also have one for trim() ?

 

following error is what I retrieve right now:

line.trim is not a function 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jul 02, 2025 Jul 02, 2025

never mind, @m1b ! 

Seems like the following worked!

// --- Polyfill: String.prototype.trim (for old ExtendScript/CS versions) ---
if (!String.prototype.trim) {
    String.prototype.trim = function() {
        return this.replace(/^\s+|\s+$/g, "");
    };
}



Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 03, 2025 Jul 03, 2025
LATEST

Looks good!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines