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
相关产品推荐
相关产品推荐

