You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Adobe Illustrator JSX脚本无法替换符号内文本的求助

问题:Illustrator JSX脚本符号内文本替换失效

我编写了一款Adobe Illustrator JSX脚本,功能包括从CSV读取数据、放置预定义符号并根据CSV数据缩放符号、断开符号链接后替换两个文本字符串(此功能失效)。其余功能正常,符号内文本框命名已匹配要求,调试无报错,但最终日期和值替换数均为0。

脚本代码

(function() {
    alert("This version uses breakLink() to safely access text frames inside symbols.");

    var SYMBOL_NAME = "syFlow";
    var DATE_TEXT_NAME = "date_field";
    var VALUE_TEXT_NAME = "value_field";
    var OUTPUT_LAYER_NAME = "SCRIPT_OUTPUT";

    var START_X = 50, START_Y = 500, SPACING = 80, BASE_VALUE = 100;

    function findTextFramesRecursive(item, name) {
        var results = [];
        if (!item) return results;
        try { 
            if (item.typename === "TextFrame" && item.name === name) results.push(item); 
        } catch(e){}
        if (item.pageItems && item.pageItems.length) {
            for (var i=0; i<item.pageItems.length; i++) {
                results = results.concat(findTextFramesRecursive(item.pageItems[i], name));
            }
        }
        return results;
    }

    var doc = app.activeDocument;
    if (!doc) { alert("No active document."); return; }

    var outputLayer;
    try { outputLayer = doc.layers.getByName(OUTPUT_LAYER_NAME); }
    catch(e) { outputLayer = doc.layers.add(); outputLayer.name = OUTPUT_LAYER_NAME; }
    outputLayer.locked = false;
    outputLayer.visible = true;

    // --- CSV Parsing ---
    var csvFile = File.openDialog("Select CSV");
    if (!csvFile) return;
    csvFile.open("r");
    var rows = [];
    while (!csvFile.eof) {
        var line = csvFile.readln().replace(/^\s+|\s+$/g,"");
        if (!line || line.charAt(0)==="#" || line.indexOf("result,")===0 || line.indexOf("date,")===0) continue;
        var parts = line.split(",");
        if (parts.length<2) continue;
        var dateStr = parts[0];
        var valueNum = parseFloat(parts[1]);
        if (!isNaN(valueNum)) rows.push({ date: dateStr, value: Math.ceil(valueNum) });
    }
    csvFile.close();
    if (rows.length===0) { alert("No valid rows found in CSV."); return; }

    // --- Symbol Reference ---
    var symbolRef;
    try { symbolRef = doc.symbols.getByName(SYMBOL_NAME); }
    catch(e) { alert("Symbol not found: "+SYMBOL_NAME); return; }

    // --- Counters ---
    var itemsCreated=0, dateR=0, valueR=0, failures=0;

    for (var r=0; r<rows.length; r++) {
        var row = rows[r];

        // Place symbol
        var inst = outputLayer.symbolItems.add(symbolRef);
        inst.left = START_X + r*SPACING;
        inst.top = START_Y;
        inst.resize((row.value/BASE_VALUE)*100,(row.value/BASE_VALUE)*100);

        // Break the link to get editable objects
        var brokenItem = inst.breakLink();
        if (!brokenItem) { failures++; continue; }

        // Recursively find text frames
        var dateTFs = findTextFramesRecursive(brokenItem, DATE_TEXT_NAME);
        var valueTFs = findTextFramesRecursive(brokenItem, VALUE_TEXT_NAME);

        var foundText = false;

        for (var j=0; j<dateTFs.length; j++) { dateTFs[j].contents = row.date; dateR++; foundText=true; }
        for (var j=0; j<valueTFs.length; j++) { valueTFs[j].contents = String(row.value); valueR++; foundText=true; }

        if (foundText) itemsCreated++; else failures++;
    }

    alert("Finished.\nItems created: "+itemsCreated+
          "\nDate replacements: "+dateR+
          "\nValue replacements: "+valueR+
          "\nFailures: "+failures);

   })();

示例CSV数据

date,value,measurement
01.05.2025,157.085,hydro
01.05.2025,156.079,hydro
01.05.2025,173.71,hydro
01.05.2025,248.727,hydro
01.05.2025,261.699,hydro
01.05.2025,258.117,hydro
01.05.2025,224.146,hydro
01.05.2025,196.397,hydro
01.05.2025,169.525,hydro
01.05.2025,159.832,hydro

解决方法

1. 修正递归函数的异常捕获范围

原函数的全局try/catch会掩盖item.name访问时的潜在问题,调整为仅针对文本框的名称检查捕获异常,确保遍历逻辑不被中断:

function findTextFramesRecursive(item, name) {
    var results = [];
    if (!item) return results;
    
    // 仅针对TextFrame的name属性访问捕获异常
    if (item.typename === "TextFrame") {
        try {
            if (item.name === name) results.push(item);
        } catch(e) {}
    }
    
    // 遍历所有子元素,包括GroupItem的pageItems
    if (item.pageItems && item.pageItems.length) {
        for (var i=0; i<item.pageItems.length; i++) {
            results = results.concat(findTextFramesRecursive(item.pageItems[i], name));
        }
    }
    return results;
}

2. 验证文本框名称的正确性

  • 确保符号内的文本框本身被命名为date_field和value_field,而非其父组。
  • 手动断开一个符号链接,选中目标文本框,在Illustrator脚本控制台执行alert(app.selection[0].name),确认名称与脚本定义一致。

3. 调整缩放与断开链接的顺序

先断开符号链接再缩放,避免缩放操作导致文本框属性异常:

// 修改循环内的执行顺序
var inst = outputLayer.symbolItems.add(symbolRef);
inst.left = START_X + r*SPACING;
inst.top = START_Y;

// 先断开链接
var brokenItem = inst.breakLink();
if (!brokenItem) { failures++; continue; }

// 再缩放断开后的对象
brokenItem.resize((row.value/BASE_VALUE)*100,(row.value/BASE_VALUE)*100);

4. 添加调试日志定位问题

在递归函数中添加日志,查看遍历到的所有对象类型和名称,确认是否能找到目标文本框:

function findTextFramesRecursive(item, name) {
    var results = [];
    if (!item) return results;
    
    // 添加调试日志
    alert("当前对象类型:" + item.typename + " | 名称:" + (item.name || "无"));
    
    if (item.typename === "TextFrame") {
        try {
            if (item.name === name) results.push(item);
        } catch(e) {}
    }
    
    if (item.pageItems && item.pageItems.length) {
        for (var i=0; i<item.pageItems.length; i++) {
            results = results.concat(findTextFramesRecursive(item.pageItems[i], name));
        }
    }
    return results;
}

内容的提问来源于stack exchange,提问作者KSPR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 09:45:55