
ãIllustratorãã¢ãŒãããŒãéçšãè¡ãäžã§ã®å°ãããšãšãããã解決ããã¹ã¯ãªãã
ããæ¡ä»¶ã§ã次ã®ãããªã¢ãŒãããŒã掻çšãããŸããã
åç»ã³ã³ãã³ãã§ãåå¹ã®ãããŒãšããŠäœ¿ãããŒãããåã¢ãŒãããŒãã«äœæ

ã¢ãŒãããŒãã¯ãããããããã¢ãŒãããŒãã®è¿œå ãé çªå€æŽãèµ·ãã

ãã®éã«å°ã£ãããšãšããã®è§£æ±ºã«ã€ããŠå ±æããŸãã
空ã®ã¢ãŒãããŒããåé€
空ã®ã¢ãŒãããŒããåé€ïŒœæ©èœã¯ãæšæºæ©èœãšããŠïŒ»ã¢ãŒãããŒãããã«ã¡ãã¥ãŒããå®è¡ã§ããŸãã

ããããªããã空ã®ã¢ãŒãããŒããåé€ïŒœã³ãã³ãã¯é衚瀺ã®ãªããžã§ã¯ããããå Žåããã®ã¢ãŒãããŒãã¯åé€ããŸããããã®æ¹ãå®å šã§ããããçŸåšã®èŠãç®ã§ç©ºã®ã¢ãŒãããŒããåé€ããããããšããããŸãã
é衚瀺ã¬ã€ã€ãŒãé衚瀺ãªããžã§ã¯ããç¡èŠããŠã空ã®ã¢ãŒãããŒããåé€ããã¹ã¯ãªãããäœæããŠã¿ãŸããã

ã¹ã¯ãªãã
ã³ãŒããã³ããŒããŠããã¹ããšãã£ã¿ã«ããŒã¹ãããŠä¿åããŠã䜿ããã ãããæ¡åŒµåã.jsxã«å€æŽããã°ã¹ã¯ãªãããã¡ã€ã«ãšããŠå®è¡ã§ããŸãïŒææèšäºã«ãªã£ãŠããŸããããèªèº«ã§äœæ¥ãªããã°ç¡æã§ãïŒã
#target illustrator
app.preferences.setBooleanPreference('ShowExternalJSXWarning', false);
/*
æŠèŠ / Overview
-----------------------------------------------------------------
ã¢ãŒãããŒãäžã«è¡šç€ºãªããžã§ã¯ããååšããªãã¢ãŒãããŒããæ€åºãã
ãŸãšããŠåé€ããã¹ã¯ãªããã§ãããªãã·ã§ã³ã§é衚瀺ã®ã¬ã€ã€ãŒïŒ
ãªããžã§ã¯ãããå æããããšã¿ãªãããåãæ¿ããããŸãïŒæ¢å® ONïŒ
ç¡èŠïŒããã°ã«ã«å¿ããŠå¯Ÿè±¡æ°è¡šç€ºãå³ææŽæ°ããŸãã
é衚瀺å€å®ã¯ç¥å
ãé¡ã£ãŠè¡ããããã°ã«ãŒãå
ã®é衚瀺ã¢ã€ãã ã
é衚瀺ã°ã«ãŒãïŒã¬ã€ã€ãŒé
äžã®ã¢ã€ãã ãåãæ±ãã«ãªããŸãã
Detects artboards that contain no occupants and removes them in a
single pass. A checkbox toggles whether hidden layers/items are
counted as occupants (ON by default = ignore hidden). The count
summary updates live with the checkbox state. Visibility is checked
up the ancestor chain, so items nested inside hidden groups or
layers (and individually hidden items inside visible groups) are
handled the same way.
*/
// =========================================
// ããŒãžã§ã³ãšããŒã«ã©ã€ãº / Version & Localization
// =========================================
var SCRIPT_VERSION = "v1.0.0";
function getCurrentLang() {
return ($.locale.indexOf("ja") === 0) ? "ja" : "en";
}
var lang = getCurrentLang();
/* æ¥è±ã©ãã«å®çŸ© / Japanese-English label definitions */
var LABELS = {
dialogTitle: { ja: "空ã¢ãŒãããŒãã®åé€", en: "Remove Empty Artboards" },
ignoreHidden: { ja: "é衚瀺ã¬ã€ã€ãŒãé衚瀺ãªããžã§ã¯ãã¯ç¡èŠ", en: "Ignore hidden layers and hidden objects" },
removalTarget: { ja: "åé€å¯Ÿè±¡ã¢ãŒãããŒãæ°", en: "Artboards to remove" },
cancel: { ja: "ãã£ã³ã»ã«", en: "Cancel" },
noDocument: { ja: "ããã¥ã¡ã³ããéãããŠããŸããã", en: "No document is open." },
onlyOneArtboard: { ja: "ã¢ãŒãããŒãã1æãããªãããåé€ã§ããŸããã", en: "Only one artboard exists; cannot remove." }
};
/* ã©ãã«ååŸ / Get localized label by key */
function L(key) {
return LABELS[key][lang];
}
/* ã³ãã³ä»ãã©ãã«ïŒæ¥æ¬èªã¯å
šè§ãè±èªã¯åè§ïŒ/ Label with colon (full-width JA, half-width EN) */
function labelText(key) {
return L(key) + (lang === 'ja' ? 'ïŒ' : ':');
}
/* ä»¶æ°ä»ãã©ãã«ïŒæ¥æ¬èªã¯å
šè§æ¬åŒ§ãè±èªã¯åè§æ¬åŒ§ïŒ/ Label with count (full-width JA parentheses, half-width EN parentheses) */
function labelWithCount(key, count) {
if (lang === 'ja') {
return L(key) + 'ïŒ' + count + 'ïŒ';
}
return L(key) + ' (' + count + ')';
}
// =========================================
// ã¢ãŒãããŒãå€å® / Artboard detection
// =========================================
/* 2 ç©åœ¢ã®äº€å·®å€å® / Test whether two rectangles overlap.
ç©åœ¢ã¯ [left, top, right, bottom] / Rectangles are [left, top, right, bottom] */
function rectsOverlap(artboardRect, itemBounds) {
return (
itemBounds[0] < artboardRect[2] &&
itemBounds[2] > artboardRect[0] &&
itemBounds[1] > artboardRect[3] &&
itemBounds[3] < artboardRect[1]
);
}
/* ãªããžã§ã¯ããšç¥å
ããã¹ãŠè¡šç€ºç¶æ
ã / Walk ancestry: every ancestor must be visible */
function isItemVisible(pageItem) {
try {
var node = pageItem;
while (node && node.typename !== "Document") {
if (node.typename === "Layer") {
if (node.visible === false) return false;
} else if (node.hidden) {
return false;
}
node = node.parent;
}
} catch (err) {
return false;
}
return true;
}
/* ã¢ãŒãããŒãäžã«å æãªããžã§ã¯ããååšããã / Any occupant touching this artboard?
ignoreHidden=true ãªãé衚瀺ã¯ç¡èŠïŒvisibleBoundsïŒ/ When ignoreHidden, skip hidden items.
ignoreHidden=false ãªãé衚瀺ãå æãšã¿ãªãïŒgeometricBoundsïŒ/ Otherwise hidden items count too. */
function hasOccupantOnArtboard(doc, artboardRect, ignoreHidden) {
var pageItems = doc.pageItems;
for (var i = 0; i < pageItems.length; i++) {
var pageItem = pageItems[i];
var visible = isItemVisible(pageItem);
if (ignoreHidden && !visible) continue;
try {
var bounds = visible ? pageItem.visibleBounds : pageItem.geometricBounds;
if (rectsOverlap(artboardRect, bounds)) return true;
} catch (err) {
// bounds ãååŸã§ããªãå Žåã¯ç¡èŠ / Skip items without bounds
}
}
return false;
}
/* 空ã¢ãŒãããŒãã®ã€ã³ããã¯ã¹äžèЧ / Collect indices of empty artboards */
function findEmptyArtboardIndices(doc, ignoreHidden) {
var indices = [];
var artboards = doc.artboards;
for (var i = 0; i < artboards.length; i++) {
if (!hasOccupantOnArtboard(doc, artboards[i].artboardRect, ignoreHidden)) {
indices.push(i);
}
}
return indices;
}
// =========================================
// ã¢ãŒãããŒãåé€ / Artboard removal
// =========================================
/* æå®ã€ã³ããã¯ã¹ã®ã¢ãŒãããŒããåé€ïŒæåŸã®1æã¯æ®ãïŒ
Remove artboards at the given indices (must leave at least one) */
function removeArtboardsByIndices(doc, indices) {
var artboards = doc.artboards;
var removedCount = 0;
for (var i = indices.length - 1; i >= 0; i--) {
if (artboards.length <= 1) break;
try {
artboards[indices[i]].remove();
removedCount++;
} catch (err) { }
}
return removedCount;
}
// =========================================
// ãã€ã¢ãã° / Dialog
// =========================================
/* ãªãã·ã§ã³ãã€ã¢ãã° / Show options dialog, return user choice or null on cancel.
察象æ°ã 0 ã®ãšã㯠OK ããã£ã 衚瀺 / OK is disabled when count is 0.
countIgnore: é衚瀺ãç¡èŠããå Žåã®å¯Ÿè±¡æ° / count when ignoring hidden
countAll: é衚瀺ãå æãšã¿ãªããå Žåã®å¯Ÿè±¡æ° / count when hidden counts as occupant */
function showOptionsDialog(countIgnore, countAll) {
var dialog = new Window('dialog', L('dialogTitle') + ' ' + SCRIPT_VERSION);
dialog.orientation = 'column';
dialog.alignChildren = 'fill';
dialog.margins = 16;
dialog.spacing = 12;
/* åé€å¯Ÿè±¡æ°ã®è¡šç€º / Count summary */
var countText = dialog.add('statictext', undefined, labelText('removalTarget') + countIgnore);
/* ãªãã·ã§ã³: é衚瀺èŠçŽ ãç¡èŠ / Option: ignore hidden elements */
var hiddenCheckbox = dialog.add('checkbox', undefined, L('ignoreHidden'));
hiddenCheckbox.value = true;
/* ãã¿ã³è¡ (Mac èŠçŽ: Cancel â OK) / Button row (Mac convention) */
var buttonGroup = dialog.add('group');
buttonGroup.alignment = 'right';
buttonGroup.add('button', undefined, L('cancel'), { name: 'cancel' });
var okButton = buttonGroup.add('button', undefined, 'OK', { name: 'ok' });
okButton.enabled = (countIgnore > 0);
/* ãã§ãã¯ããã¯ã¹é£åã§ä»¶æ°ãš OK 掻æ§ãæŽæ° / Sync count and OK state on toggle */
hiddenCheckbox.onClick = function () {
var c = hiddenCheckbox.value ? countIgnore : countAll;
countText.text = labelText('removalTarget') + c;
okButton.enabled = (c > 0);
};
if (dialog.show() !== 1) return null;
return { ignoreHidden: hiddenCheckbox.value };
}
// =========================================
// ã¡ã€ã³ / Main
// =========================================
(function main() {
if (app.documents.length === 0) {
alert(L('noDocument'));
return;
}
var doc = app.activeDocument;
if (doc.artboards.length <= 1) {
alert(L('onlyOneArtboard'));
return;
}
var indicesIgnore = findEmptyArtboardIndices(doc, true);
var indicesAll = findEmptyArtboardIndices(doc, false);
var options = showOptionsDialog(indicesIgnore.length, indicesAll.length);
if (!options) return;
var emptyIndices = options.ignoreHidden ? indicesIgnore : indicesAll;
removeArtboardsByIndices(doc, emptyIndices);
})();
çŸåšã®ã¢ãŒãããŒã以å€ãã³ã³ãã³ããå«ããŠåé€
ã¢ãŒãããŒãããã«ã«ã¯ãã¢ãŒãããŒããåé€ãããã¿ã³ã¯ãããŸãããã¢ãŒãããŒãäžã®ãªããžã§ã¯ããšã¯ç¡é¢ä¿ã§ãã
çŸåšã®ã¢ãŒãããŒããšãã®ã¢ãŒãããŒãäžã®ãªããžã§ã¯ãé£²ã¿æ®ãããã以å€ã®ã¢ãŒãããŒããšãªããžã§ã¯ããåé€ããã¹ã¯ãªããã§ãã
#target illustrator
app.preferences.setBooleanPreference('ShowExternalJSXWarning', false);
(function () {
// ã¹ã¯ãªããããŒãžã§ã³
var SCRIPT_VERSION = "v1.2";
// ç©åœ¢ã®äº€å·®å€å®ïŒ[top,left,bottom,right]ïŒ/ Rectangle intersection test
function rectanglesIntersect(rectA, rectB) {
// å³ < å·Š / left > right / äž < äž ã®ããããã§é亀差
if (rectA[3] < rectB[1]) return false; // a.right < b.left
if (rectA[1] > rectB[3]) return false; // a.left > b.right
if (rectA[0] < rectB[2]) return false; // a.top < b.bottom
if (rectA[2] > rectB[0]) return false; // a.bottom > b.top
return true;
}
// artboardRect([left, top, right, bottom]) â [top, left, bottom, right]
function artboardRectToBounds(artboardRect) {
return [artboardRect[1], artboardRect[0], artboardRect[3], artboardRect[2]];
}
// ç¹ãç©åœ¢å
ã«ãããïŒå«ãå¢çïŒ/ Point-in-rect (inclusive)
function isPointInRect(x, y, rect) { // rect: [left, top, right, bottom]
return (x >= rect[0] && x <= rect[2] && y <= rect[1] && y >= rect[3]);
}
// 2Dãã¯ãã«å€ç© / Cross product helper
function cross2D(ax, ay, bx, by) {
return ax * by - ay * bx;
}
// ç·åå士ã®äº€å·®å€å®ïŒåº§æšïŒ/ Segment-segment intersection
function segmentsIntersect(p1x, p1y, p2x, p2y, q1x, q1y, q2x, q2y) {
var pDx = p2x - p1x,
pDy = p2y - p1y;
var qDx = q2x - q1x,
qDy = q2y - q1y;
var denominator = cross2D(pDx, pDy, qDx, qDy);
var p1ToQ1Dx = q1x - p1x,
p1ToQ1Dy = q1y - p1y;
if (denominator === 0) {
// å¹³è¡ïŒå«ãå
±ç·ïŒ/ Parallel (including collinear)
// å
±ç·ã®å Žåãæåœ±ã§éãªããã§ãã¯ïŒç°¡æïŒ/ If collinear, check overlap via projection
var collinearCross = cross2D(p1ToQ1Dx, p1ToQ1Dy, pDx, pDy);
if (Math.abs(collinearCross) > 1e-6) return false; // éå
±ç· / not collinear
// è»žã«æ²¿ã£ãŠéãªãå€å® / overlap on x/y
var minPx = Math.min(p1x, p2x),
maxPx = Math.max(p1x, p2x);
var minQx = Math.min(q1x, q2x),
maxQx = Math.max(q1x, q2x);
var minPy = Math.min(p1y, p2y),
maxPy = Math.max(p1y, p2y);
var minQy = Math.min(q1y, q2y),
maxQy = Math.max(q1y, q2y);
var overlapX = !(maxPx < minQx || maxQx < minPx);
var overlapY = !(maxPy < minQy || maxQy < minPy);
return overlapX && overlapY;
}
var tParam = cross2D(p1ToQ1Dx, p1ToQ1Dy, qDx, qDy) / denominator;
var uParam = cross2D(p1ToQ1Dx, p1ToQ1Dy, pDx, pDy) / denominator;
return (tParam >= 0 && tParam <= 1 && uParam >= 0 && uParam <= 1);
}
// ç·åãšç©åœ¢ã®äº€å·®å€å® / Segment-rectangle intersection
function segmentIntersectsRect(x1, y1, x2, y2, rect) { // rect: [left, top, right, bottom]
// 端ç¹ã®ã©ã¡ãããç©åœ¢å
if (isPointInRect(x1, y1, rect) || isPointInRect(x2, y2, rect)) return true;
// ç©åœ¢ã®4蟺
var left = rect[0],
top = rect[1],
right = rect[2],
bottom = rect[3];
// äžèŸº (left,top)-(right,top)
if (segmentsIntersect(x1, y1, x2, y2, left, top, right, top)) return true;
// äžèŸº (left,bottom)-(right,bottom)
if (segmentsIntersect(x1, y1, x2, y2, left, bottom, right, bottom)) return true;
// 巊蟺 (left,top)-(left,bottom)
if (segmentsIntersect(x1, y1, x2, y2, left, top, left, bottom)) return true;
// å³èŸº (right,top)-(right,bottom)
if (segmentsIntersect(x1, y1, x2, y2, right, top, right, bottom)) return true;
return false;
}
// ãã¹ãã¢ãŒãããŒãç©åœ¢ã«éãªããïŒç«¯ç¹å
å
or ç·å亀差ïŒ/ Does path overlap artboard rect?
function pathIntersectsArtboard(pathItem, artboardRect) { // artboardRect: [left, top, right, bottom]
try {
var pathPoints = pathItem.pathPoints;
if (!pathPoints || pathPoints.length === 0) return false;
for (var i = 0; i < pathPoints.length; i++) {
var currentAnchor = pathPoints[i].anchor; // [x, y]
var nextAnchor = pathPoints[(i + 1) % pathPoints.length].anchor; // next (wrap if closed)
// éãã¹ã§æåŸã®ã»ã°ã¡ã³ãã¯çµã°ãªã / For open paths, skip last-to-first
if (!pathItem.closed && i === pathPoints.length - 1) break;
if (segmentIntersectsRect(currentAnchor[0], currentAnchor[1], nextAnchor[0], nextAnchor[1], artboardRect)) return true;
}
return false;
} catch (e) {
return false;
}
}
// ã¬ã€ã€ãŒ/ã°ã«ãŒãã®ç¶æ
ãååž°çã«ä¿åãäžæçã«è§£é€ãããŠãŒãã£ãªãã£
// Utilities to recursively capture and relax layer/group states
function collectLayerStates(layer, stateLog) {
// å
ç¶æ
ãèšé² / Record original state
stateLog.push({
type: 'Layer',
ref: layer,
locked: layer.locked,
visible: layer.visible,
template: layer.template
});
// äžæè§£é€ / Relax temporarily
layer.locked = false;
layer.visible = true;
if (layer.template === true) layer.template = false;
// ãµãã¬ã€ã€ãŒ / Sublayers
for (var i = 0; i < layer.layers.length; i++) {
collectLayerStates(layer.layers[i], stateLog);
}
// ã°ã«ãŒã / Groups within this layer
for (var j = 0; j < layer.groupItems.length; j++) {
collectGroupStates(layer.groupItems[j], stateLog);
}
// ã¬ã€ã€ãŒçŽäžã¢ã€ãã / Items directly under this layer
collectItemStatesInLayer(layer, stateLog);
}
function collectGroupStates(groupItem, stateLog) {
stateLog.push({
type: 'Group',
ref: groupItem,
locked: groupItem.locked,
visible: groupItem.visible
});
groupItem.locked = false;
groupItem.visible = true;
// ãã¹ãã°ã«ãŒã / Nested groups
for (var i = 0; i < groupItem.groupItems.length; i++) {
collectGroupStates(groupItem.groupItems[i], stateLog);
}
// ã°ã«ãŒãçŽäžã¢ã€ãã / Items directly under this group
collectItemStatesInGroup(groupItem, stateLog);
}
// ã¬ã€ã€ãŒé
äžã® PageItem ã®ç¶æ
ãä¿åãäžæè§£é€ / Collect & relax PageItems under a layer
function collectItemStatesInLayer(layer, stateLog) {
try {
var items = layer.pageItems;
for (var i = 0; i < items.length; i++) {
var item = items[i];
stateLog.push({
type: 'Item',
ref: item,
locked: item.locked,
hidden: item.hidden
});
// äžæè§£é€ / Relax temporarily
if (item.locked) item.locked = false;
if (item.hidden) item.hidden = false;
}
} catch (e) {}
}
// ã°ã«ãŒãé
äžã® PageItem ã®ç¶æ
ãä¿åãäžæè§£é€ / Collect & relax PageItems under a group
function collectItemStatesInGroup(groupItem, stateLog) {
try {
var items = groupItem.pageItems;
for (var i = 0; i < items.length; i++) {
var item = items[i];
stateLog.push({
type: 'Item',
ref: item,
locked: item.locked,
hidden: item.hidden
});
if (item.locked) item.locked = false;
if (item.hidden) item.hidden = false;
}
} catch (e) {}
}
function captureAndUnlockStructure(doc) {
var stateLog = [];
for (var i = 0; i < doc.layers.length; i++) {
collectLayerStates(doc.layers[i], stateLog);
}
return stateLog;
}
function restoreStructure(savedStates) {
// éé ã§åŸ©å
ïŒäžäœâäžäœïŒ/ Restore in reverse (bottom-up)
for (var i = savedStates.length - 1; i >= 0; i--) {
var state = savedStates[i];
try {
if (state.type === 'Layer') {
state.ref.locked = state.locked;
state.ref.visible = state.visible;
state.ref.template = state.template;
} else if (state.type === 'Group') {
state.ref.locked = state.locked;
state.ref.visible = state.visible;
} else if (state.type === 'Item') {
state.ref.locked = state.locked;
state.ref.hidden = state.hidden;
}
} catch (e) {}
}
}
function main() {
// ã¢ã¯ãã£ããªããã¥ã¡ã³ããååŸ / Get the active document
var doc = app.activeDocument;
// ã¢ãŒãããŒãã®ç·æ°ãååŸ / Get total number of artboards
var totalArtboards = doc.artboards.length;
// ã¢ãŒãããŒãã1ã€ã ãã®å Žåã¯äœãããªã / Do nothing if only one artboard exists
if (totalArtboards > 1) {
// ã¢ã¯ãã£ããªã¢ãŒãããŒãã®ã€ã³ããã¯ã¹ãååŸ / Get index of the active artboard
var activeArtboardIndex = doc.artboards.getActiveArtboardIndex();
// æåŸããã¢ãŒãããŒããåé€ïŒã¢ã¯ãã£ããªã¢ãŒãããŒã以å€ïŒ / Remove artboards from the end, except the active one
for (var i = totalArtboards - 1; i >= 0; i--) {
if (i !== activeArtboardIndex) {
doc.artboards.remove(i);
}
}
}
// ã¬ã€ã€ãŒ/ãµãã¬ã€ã€ãŒ/ã°ã«ãŒãã®ããã¯ã»è¡šç€ºã»ãã³ãã¬ãŒããååž°çã«äžæè§£é€ / Recursively relax lock/visible/template on layers, sublayers, and groups
var savedStructureStates = captureAndUnlockStructure(doc);
// ã¢ã¯ãã£ãArtboardãšéãªããªãã¬ã€ãïŒãªããžã§ã¯ãã¬ã€ãïŒãåé€ïŒããŠã³ãã£ã³ã°ã§ã¯ãªããã¹ã®å®äœã§å€å®ïŒ
// Delete object guides that do NOT overlap the active artboard (check path segments, not only bounds)
try {
var activeArtboardIndex = doc.artboards.getActiveArtboardIndex();
var artboardRect = doc.artboards[activeArtboardIndex].artboardRect; // [left, top, right, bottom]
var guidesToRemove = [];
for (var i = doc.pageItems.length - 1; i >= 0; i--) {
var item = doc.pageItems[i];
if (item.guides === true) {
var intersectsArtboard = false;
// CompoundPathItem / PathItem ã®äž¡æ¹ã«å¯Ÿå¿
if (item.typename === 'CompoundPathItem') {
var subPaths = item.pathItems;
for (var j = 0; j < subPaths.length && !intersectsArtboard; j++) {
if (pathIntersectsArtboard(subPaths[j], artboardRect)) intersectsArtboard = true;
}
} else if (item.typename === 'PathItem') {
if (pathIntersectsArtboard(item, artboardRect)) intersectsArtboard = true;
} else {
// ãã®ä»ã¯ããŠã³ãã£ã³ã°ã§ãã©ãŒã«ããã¯
var geometricBounds = item.geometricBounds; // [top, left, bottom, right]
var artboardBounds = [artboardRect[0], artboardRect[1], artboardRect[2], artboardRect[3]]; // [left, top, right, bottom]
// geometricBounds [top,left,bottom,right] ã [left,top,right,bottom] ãžå€æ
var boundsRect = [geometricBounds[1], geometricBounds[0], geometricBounds[3], geometricBounds[2]];
// ç°¡æäº€å·®: 端ç¹å
å
ãªãã®ç©åœ¢äº€å·®
intersectsArtboard = !(boundsRect[2] < artboardBounds[0] || boundsRect[0] > artboardBounds[2] || boundsRect[1] < artboardBounds[3] || boundsRect[3] > artboardBounds[1]);
}
if (!intersectsArtboard) guidesToRemove.push(item);
}
}
for (var k = 0; k < guidesToRemove.length; k++) guidesToRemove[k].remove();
} catch (e) {
// å¯èœãªç¯å²ã§å®æœïŒã«ãŒã©ãŒã¬ã€ãã¯å¯Ÿè±¡å€ïŒ/ Best-effort (ruler guides excluded)
}
// ã¢ã¯ãã£ããªã¢ãŒãããŒãäžã®å
šãªããžã§ã¯ããéžæâå転âåé€
// Select all on active artboard, invert selection, then delete
app.executeMenuCommand('selectallinartboard');
app.executeMenuCommand('Inverse menu item');
app.executeMenuCommand('clear');
// å
ã
ããã¯ãããŠããã¬ã€ã€ãŒãåãã㯠/ Re-lock layers that were originally locked
// ã¬ã€ã€ãŒ/ãµãã¬ã€ã€ãŒ/ã°ã«ãŒãã®ç¶æ
ã埩å
/ Restore layers/sublayers/groups state
restoreStructure(savedStructureStates);
}
main();
})();ãªããžã§ã¯ããããããã®ã¢ãŒãããŒãã®äžå€®äžã«é 眮ãã
以åãåãçµãã§ãããã®ããªãã¡ã€ã³ããŸããã
倿Žç¹
æŽåå ïŒåºæºç¹ïŒã9åã«
ãã¬ãã¥ãŒå¢çã䜿çšïŒœãªãã·ã§ã³ã远å

#target illustrator
app.preferences.setBooleanPreference('ShowExternalJSXWarning', false);
/*
ãæŠèŠ / Summaryã
è€æ°ã¢ãŒãããŒãã®ããã¥ã¡ã³ãã§ãéžæäžã®ãªããžã§ã¯ããåã¢ãŒãããŒãäžã®æå®äœçœ®ãžæŽåããŸãã
ãã€ã¢ãã°è¡šç€ºäžã¯ã©ã€ããã¬ãã¥ãŒã§çµæã確èªã§ããOKã§ç¢ºå®ããã£ã³ã»ã«ïŒœãŸãã¯éããæäœã§å
ã®äœçœ®ãžæ»ããŸãã
### æŽåã®åºæº
- ãã¹ãŠã®ã¢ãŒãããŒãïŒéžæãªããžã§ã¯ããäžå¿ç¹ãå±ããã¢ãŒãããŒãããšã«æ¯ãåããåã¢ãŒãããŒãå
ã®æå®äœçœ®ãžæŽåããŸãã
- ã¢ã¯ãã£ããåºæºïŒã¢ã¯ãã£ãã¢ãŒãããŒãäžã®éžæãåºæºã«ãä»ã®ã¢ãŒãããŒãäžã®éžæãåãçžå¯Ÿäœçœ®ãžæŽåããŸããã¢ã¯ãã£ãåŽã®ãªããžã§ã¯ãã¯ç§»åããŸããã
### æŽåå
- 3Ã3 ã®9ç¹ããæŽåäœçœ®ãéžæã§ããŸãïŒå·ŠäžïŒäžäžå€®ïŒå³äžïŒå·Šäžå€®ïŒäžå€®ïŒå³äžå€®ïŒå·ŠäžïŒäžäžå€®ïŒå³äž
- ããã¹ãŠã®ã¢ãŒãããŒããéžææã¯ãéžæãã9ç¹ãåãªããžã§ã¯ãã®æŽåã¢ã³ã«ãŒãšããŠäœ¿çšããŸãã
- ãã¢ã¯ãã£ããåºæºãéžææã¯ãçŸåšéžæãããŠããæŽåå
ãåºæºã«çžå¯Ÿäœçœ®ãååŸããŸããæŽåå
ããã«ã¯ç¡å¹è¡šç€ºã«ãªãããã®æç¹ã®éžæãç¶æãããŸãã
- ãäžå€®ãéžææã¯ããŒãžã³ã¯ç¡å¹ïŒ0æ±ãïŒã§ããäžäžå€®ïŒäžäžå€®ã§ã¯å·Šå³ããŒãžã³ãå·Šäžå€®ïŒå³äžå€®ã§ã¯äžäžããŒãžã³ã䜿ããŸããã
### ããŒãžã³ïŒå·Šå³ïŒäžäžïŒ
- ããã¹ãŠã®ã¢ãŒãããŒããéžææã察å¿ãã蟺ããå
åŽãžãªãã»ããã§ããŸãã
- å·Šå³ã»äžäžãå¥ã
ã«æå®ã§ããŸãããé£åãON ã®ãšãã¯ãå·Šå³ã®å
¥åå€ãäžäžã«ãåæ ããŸãïŒããã©ã«ãïŒONïŒã
- å
¥ååäœã¯ Illustrator ã®ã«ãŒã©ãŒåäœïŒrulerTypeïŒã«é£åããå
éšã§ã¯ pt ã«å€æããŠåŠçããŸãã
- ãã¢ã¯ãã£ããåºæºãéžææã¯ãããŒãžã³ã¯ç¡å¹ïŒ0æ±ãïŒã§ãã
### å¢çãšæäœ
- ããã¬ãã¥ãŒå¢çã䜿çšãONïŒç·å¹
ã广ãå«ãèŠãç®ã®å¢çã§æŽåããŸããOFFïŒå³åœ¢æ¬äœã®å¹Ÿäœå¢çã§æŽåããŸãã
- æŽåå
ã¯ããŒããŒãã§ãéžæã§ããŸãïŒq=å·Šäž / w=äžäžå€® / e=å³äž / a=å·Šäžå€® / s=äžå€® / d=å³äžå€® / z=å·Šäž / x=äžäžå€® / c=å³äž
- æŽåã®åºæºã¯ããŒããŒãã§ãéžæã§ããŸãïŒ1=ãã¹ãŠã®ã¢ãŒãããŒã / 2=ã¢ã¯ãã£ããåºæº
- ããŒãžã³æ¬ã¯ ââ ã§å¢æžïŒShift=±10ãOption=±0.1ïŒããå
¥åäžããã¬ãã¥ãŒãæŽæ°ãããŸãã
- Enter/Return ããŒã§ïŒ»OKãå®è¡ã§ããŸãã
æŽæ°æ¥ / Updated: 2026-05-15
*/
// =========================================
// ããŒãžã§ã³ / Version
// =========================================
var SCRIPT_VERSION = "v1.1.2";
// =========================================
// ããŒã«ã©ã€ãº / Localization
// =========================================
/* çŸåšã®ãã±ãŒã«ãå€å® / Detect current locale */
function getCurrentLang() {
return ($.locale.indexOf("ja") === 0) ? "ja" : "en";
}
var lang = getCurrentLang();
/* ãã±ãŒã«ã«å¿ããŠã©ãã«ãåæ¿ / Switch label by locale */
function _(ja, en) {
return (lang === "ja") ? ja : en;
}
var LABELS = {
dialogTitle: { ja: "åã¢ãŒãããŒãã«æŽå " + SCRIPT_VERSION, en: "Align to Artboards " + SCRIPT_VERSION },
targetCorner: { ja: "æŽåå
", en: "Target" },
target: { ja: "æŽåã®åºæº", en: "Align based on" },
targetArtboard: { ja: "ãã¹ãŠã®ã¢ãŒãããŒã", en: "All Artboards" },
targetSelection: { ja: "ã¢ã¯ãã£ããåºæº", en: "Based on Active Artboard" },
targetArtboardTip: { ja: "éžæãªããžã§ã¯ããäžå¿ç¹ãå±ããã¢ãŒãããŒãããšã«æ¯ãåããåã¢ãŒãããŒãå
ã®æå®äœçœ®ãžæŽåããŸãã", en: "Groups selected objects by the artboard containing their center point, then aligns them to the selected position on each artboard." },
targetSelectionTip: { ja: "ã¢ã¯ãã£ãã¢ãŒãããŒãäžã®éžæãåºæºã«ãä»ã®ã¢ãŒãããŒãäžã®éžæãåãçžå¯Ÿäœçœ®ãžæŽåããŸããã¢ã¯ãã£ãåŽã¯åãããŸããã", en: "Uses the selection on the active artboard as the reference and aligns selections on other artboards to the same relative position. Objects on the active artboard are not moved." },
targetCornerTip: { ja: "æŽåå
ã®9ç¹ãéžæããŸããã¢ã¯ãã£ããåºæºã«ããå Žåã¯ããã®æç¹ã®éžæãç¶æãããŸãã", en: "Choose one of the 9 alignment positions. When using Based on Active Artboard, the current choice is preserved." },
marginTip: { ja: "察å¿ãã蟺ããå
åŽãžãªãã»ããããŸããäžå€®ãŸãã¯ã¢ã¯ãã£ããåºæºã«ããå Žåã¯ç¡å¹ã§ãã", en: "Offsets objects inward from the corresponding edge. Disabled for Center and Based on Active Artboard." },
linkTip: { ja: "ONã®ãšãã¯å·Šå³ã®å€ãäžäžã«ãé£åããŸãã", en: "When enabled, the horizontal value is also used for the vertical margin." },
usePreviewBoundsTip: { ja: "ONïŒç·å¹
ã广ãå«ãèŠãç®ã®å¢çã§æŽåãOFFïŒå³åœ¢æ¬äœã®å¹Ÿäœå¢çã§æŽåã", en: "On: align by visual bounds including strokes and effects. Off: align by geometric bounds of the object shape." },
leftTop: { ja: "å·Šäž", en: "Top-Left" },
topCenter: { ja: "äžäžå€®", en: "Top-Center" },
rightTop: { ja: "å³äž", en: "Top-Right" },
leftMiddle: { ja: "å·Šäžå€®", en: "Middle-Left" },
center: { ja: "äžå€®", en: "Center" },
rightMiddle: { ja: "å³äžå€®", en: "Middle-Right" },
leftBottom: { ja: "å·Šäž", en: "Bottom-Left" },
bottomCenter: { ja: "äžäžå€®", en: "Bottom-Center" },
rightBottom: { ja: "å³äž", en: "Bottom-Right" },
marginValue: { ja: "ããŒãžã³", en: "Margin" },
marginX: { ja: "å·Šå³", en: "Horizontal" },
marginY: { ja: "äžäž", en: "Vertical" },
link: { ja: "é£å", en: "Linked" },
usePreviewBounds: { ja: "ãã¬ãã¥ãŒå¢çã䜿çš", en: "Use Preview Bounds" },
ok: { ja: "OK", en: "OK" },
cancel: { ja: "ãã£ã³ã»ã«", en: "Cancel" }
};
// =========================================
// å¢çååŸïŒãã¬ãã¥ãŒå¢ç or 幟äœå¢çïŒ / Bounds resolver
// ãã¬ãã¥ãŒå¢çïŒã¹ãããŒã¯ã»å¹æãå«ãã幟äœå¢çïŒå³åœ¢ã®ã¿ / Preview bounds include strokes/effects; geometric bounds use the object shape only
// =========================================
var usePreviewBounds = true;
/* ã¢ã€ãã ã®æŽåçšããŠã³ãã£ã³ã°ããã¯ã¹ãè¿ã / Return item bounds for alignment */
function getItemBounds(item) {
try {
return usePreviewBounds ? item.visibleBounds : item.geometricBounds;
} catch (e) {
return null;
}
}
// =========================================
// åäœïŒrulerTypeïŒ / Units (rulerType)
// =========================================
var unitLabelMap = {
0: "in",
1: "mm",
2: "pt",
3: "pica",
4: "cm",
5: "Q/H",
6: "px",
7: "ft/in",
8: "m",
9: "yd",
10: "ft"
};
/* çŸåšã®ã«ãŒã©ãŒåäœã©ãã«ãååŸ / Get current ruler unit label */
function getCurrentUnitLabel() {
var unitCode = 2; /* åæå€ã¯pt / Default unit is pt */
try { unitCode = app.preferences.getIntegerPreference("rulerType"); } catch (e) { }
return unitLabelMap[unitCode] || "pt";
}
/* å
¥åå€ïŒçŸåšåäœïŒã pt ã«å€æ / Convert a value typed in current unit to points */
function toPt(valueNumber, unitLabel) {
if (valueNumber === null || valueNumber === undefined) return null;
if (isNaN(valueNumber)) return null;
/* UnitValueäºæã®åäœåãžæ£èŠå / Normalize unit labels for UnitValue compatibility */
var u = unitLabel;
if (u === "pica") u = "pc";
else if (u !== "in" && u !== "mm" && u !== "cm" && u !== "pt" && u !== "px") {
/* æªå¯Ÿå¿ãŸãã¯ç¹æ®ãªåäœã¯ptãšããŠæ±ã / Treat unsupported or rare units as pt */
u = "pt";
}
try {
return new UnitValue(valueNumber, u).as("pt");
} catch (eUV) {
return valueNumber; /* ãã©ãŒã«ããã¯ïŒptãšããŠæ±ã / Fallback: assume pt */
}
}
// =========================================
// ã¡ã€ã³ / Main
// =========================================
/* ãšã³ããªãŒãã€ã³ãïŒãã€ã¢ãã°ã衚瀺ããŠæŽåãå®è¡ / Entry point: show dialog and run alignment */
function main() {
if (app.documents.length === 0) return;
var doc = app.activeDocument;
if (!doc.selection || doc.selection.length === 0) return;
var input = showDialog();
if (input === null) return;
var corner = input.corner; /* 9ç¹ã³ãŒã / 9-point code: LT TC RT / LM C RM / LB BC RB */
var targetMode = input.targetMode || "artboard"; /* æŽåã®åºæº / Alignment base: "artboard" | "selection" */
var margin = input.marginPt; /* ptåäœïŒæ°å€ãŸãã¯{x, y} / In pt: number or {x, y} */
if (targetMode === "selection") {
alignByActiveArtboardReference(
doc,
doc.selection,
corner,
function (items, artboardRect, alignmentCorner, offset) {
alignGroupToArtboardWithOffset(items, artboardRect, alignmentCorner, offset);
}
);
try { app.redraw(); } catch (eRedrawMain1) { }
} else {
/* éåžžã¢ãŒãïŒåã¢ã€ãã ã®äžå¿ç¹ãåºæºã«ã¢ãŒãããŒããžæ¯ãåã / Default mode: group items by artboard using each item center */
var map = groupSelectedItemsByArtboard(doc, doc.selection);
if (!map) return;
for (var abIndex in map) {
if (!map.hasOwnProperty(abIndex)) continue;
var items = map[abIndex];
if (!items || items.length === 0) continue;
var rect = doc.artboards[parseInt(abIndex, 10)].artboardRect; /* [å·Š, äž, å³, äž] / [L, T, R, B] */
alignItemsToCornerWithMargin(items, rect, corner, margin);
}
try { app.redraw(); } catch (eRedrawMain2) { }
}
}
main();
// =========================================
// ãã€ã¢ãã° UI / Dialog UI
// =========================================
/* ãã¬ãã¥ãŒç¶æ
ãåæå / Create preview state from current selection */
function createPreviewState(doc) {
var previewState = {
items: [],
dx: [],
dy: [],
applied: false
};
try {
if (doc && doc.selection && doc.selection.length > 0) {
for (var i = 0; i < doc.selection.length; i++) {
previewState.items.push(doc.selection[i]);
previewState.dx.push(0);
previewState.dy.push(0);
}
}
} catch (e) { }
return previewState;
}
/* ãã¬ãã¥ãŒç§»åãå·»ãæ»ã / Revert preview translation */
function revertPreview(previewState, doRedraw) {
if (doRedraw === undefined) doRedraw = true;
if (!previewState || !previewState.applied) return;
for (var i = 0; i < previewState.items.length; i++) {
var item = previewState.items[i];
var dx = previewState.dx[i];
var dy = previewState.dy[i];
if (!item) continue;
try {
if (dx !== 0 || dy !== 0) item.translate(-dx, -dy);
} catch (e) { }
previewState.dx[i] = 0;
previewState.dy[i] = 0;
}
previewState.applied = false;
if (doRedraw) {
try { app.redraw(); } catch (eRedraw) { }
}
}
/* ãã¬ãã¥ãŒæŽåãé©çš / Apply preview alignment */
function applyPreview(doc, previewState, corner, marginX, marginY, targetMode) {
revertPreview(previewState, false);
if (!doc || !previewState || !previewState.items || previewState.items.length === 0) return;
if (targetMode === "selection") {
alignByActiveArtboardReference(
doc,
previewState.items,
corner,
function (items, artboardRect, alignmentCorner, offset) {
alignGroupToArtboardWithOffsetPreview(items, artboardRect, alignmentCorner, offset, previewState);
}
);
} else {
var map = groupSelectedItemsByArtboard(doc, previewState.items);
if (!map) return;
for (var abIndex in map) {
if (!map.hasOwnProperty(abIndex)) continue;
var items = map[abIndex];
if (!items || items.length === 0) continue;
var rect = doc.artboards[parseInt(abIndex, 10)].artboardRect;
alignItemsToCornerWithMarginPreviewXY(items, rect, corner, marginX, marginY, previewState);
}
}
previewState.applied = true;
try { app.redraw(); } catch (eRedraw2) { }
}
/* èšå®ãã€ã¢ãã°ã衚瀺ããå
¥åçµæãè¿ã / Show settings dialog and return user input */
function showDialog() {
var w = new Window("dialog", _(LABELS.dialogTitle.ja, LABELS.dialogTitle.en));
var unitLabel = getCurrentUnitLabel();
var doc = app.activeDocument;
var previewState = createPreviewState(doc);
var closingByOK = false; /* OKçµç±ã§éãããšãã®åæç»ãææ¢ / Suppress redraw when closing via OK */
/* UIããæŽåå
ã³ãŒããååŸ / Read the selected corner code from UI */
function getCornerFromUI() {
if (rbLT.value) return "LT";
if (rbTC.value) return "TC";
if (rbRT.value) return "RT";
if (rbLM.value) return "LM";
if (rbC.value) return "C";
if (rbRM.value) return "RM";
if (rbLB.value) return "LB";
if (rbBC.value) return "BC";
if (rbRB.value) return "RB";
return "LT";
}
/* æŽåå
ã·ã§ãŒãã«ãããç»é² / Register corner shortcut keys */
function addCornerKeyHandler(dialog) {
dialog.addEventListener("keydown", function (event) {
/* ããã¹ãå
¥åäžã¯ã·ã§ãŒãã«ãããç¡å¹å / Skip shortcuts while typing in edittext */
if (event.target && event.target.type === "edittext") return;
/* æŽåå
ããã«ãç¡å¹ã®ãšãã¯ã·ã§ãŒãã«ãããç¡å¹ / Skip shortcuts when the corner panel is disabled */
try { if (!pCorner.enabled) return; } catch (eP) { }
var k = event.keyName;
if (!k) return;
k = ("" + k).toLowerCase();
var target = null;
if (k === "q") target = rbLT;
else if (k === "w") target = rbTC;
else if (k === "e") target = rbRT;
else if (k === "a") target = rbLM;
else if (k === "s") target = rbC;
else if (k === "d") target = rbRM;
else if (k === "z") target = rbLB;
else if (k === "x") target = rbBC;
else if (k === "c") target = rbRB;
if (target) {
selectCornerRb(target);
event.preventDefault();
updatePreviewFromUI();
}
});
}
w.orientation = "column";
w.alignChildren = ["fill", "top"];
/* æŽåã®åºæºããã«ïŒå
šå¹
ã»çžŠäžŠã³ïŒ / Alignment base panel (full-width vertical radios) */
var pTarget = w.add("panel", undefined, _(LABELS.target.ja, LABELS.target.en));
pTarget.orientation = "column";
pTarget.alignChildren = ["left", "center"];
pTarget.margins = [15, 20, 15, 10];
var rbTargetArtboard = pTarget.add("radiobutton", undefined, _(LABELS.targetArtboard.ja, LABELS.targetArtboard.en));
var rbTargetSelection = pTarget.add("radiobutton", undefined, _(LABELS.targetSelection.ja, LABELS.targetSelection.en));
rbTargetSelection.value = true;
rbTargetArtboard.helpTip = _(LABELS.targetArtboardTip.ja, LABELS.targetArtboardTip.en);
rbTargetSelection.helpTip = _(LABELS.targetSelectionTip.ja, LABELS.targetSelectionTip.en);
/* ãã¢ã¯ãã£ããåºæºãéžæäžãå€å® / Check whether âBased on Active Artboardâ is selected */
function isTargetSelection() {
try { return rbTargetSelection.value === true; } catch (e) { return false; }
}
var gTop = w.add("group");
gTop.orientation = "row";
gTop.alignChildren = ["fill", "top"];
var gLeft = gTop.add("group");
gLeft.orientation = "column";
gLeft.alignChildren = ["fill", "top"];
var gRight = gTop.add("group");
gRight.orientation = "column";
gRight.alignChildren = ["fill", "top"];
gRight.alignment = ["right", "top"];
var pCorner = gLeft.add("panel", undefined, _(LABELS.targetCorner.ja, LABELS.targetCorner.en));
pCorner.orientation = "column";
pCorner.alignChildren = ["center", "top"];
pCorner.margins = [15, 18, 15, 10];
pCorner.spacing = 6;
pCorner.helpTip = _(LABELS.targetCornerTip.ja, LABELS.targetCornerTip.en);
var rowTop = pCorner.add("group");
rowTop.orientation = "row";
rowTop.alignChildren = ["center", "center"];
rowTop.spacing = 12;
var rbLT = rowTop.add("radiobutton", undefined, "");
var rbTC = rowTop.add("radiobutton", undefined, "");
var rbRT = rowTop.add("radiobutton", undefined, "");
var rowMid = pCorner.add("group");
rowMid.orientation = "row";
rowMid.alignChildren = ["center", "center"];
rowMid.spacing = 12;
var rbLM = rowMid.add("radiobutton", undefined, "");
var rbC = rowMid.add("radiobutton", undefined, "");
var rbRM = rowMid.add("radiobutton", undefined, "");
var rowBot = pCorner.add("group");
rowBot.orientation = "row";
rowBot.alignChildren = ["center", "center"];
rowBot.spacing = 12;
var rbLB = rowBot.add("radiobutton", undefined, "");
var rbBC = rowBot.add("radiobutton", undefined, "");
var rbRB = rowBot.add("radiobutton", undefined, "");
rbLT.helpTip = _(LABELS.leftTop.ja, LABELS.leftTop.en) + " (q)";
rbTC.helpTip = _(LABELS.topCenter.ja, LABELS.topCenter.en) + " (w)";
rbRT.helpTip = _(LABELS.rightTop.ja, LABELS.rightTop.en) + " (e)";
rbLM.helpTip = _(LABELS.leftMiddle.ja, LABELS.leftMiddle.en) + " (a)";
rbC.helpTip = _(LABELS.center.ja, LABELS.center.en) + " (s)";
rbRM.helpTip = _(LABELS.rightMiddle.ja, LABELS.rightMiddle.en) + " (d)";
rbLB.helpTip = _(LABELS.leftBottom.ja, LABELS.leftBottom.en) + " (z)";
rbBC.helpTip = _(LABELS.bottomCenter.ja, LABELS.bottomCenter.en) + " (x)";
rbRB.helpTip = _(LABELS.rightBottom.ja, LABELS.rightBottom.en) + " (c)";
var allCornerRadios = [rbLT, rbTC, rbRT, rbLM, rbC, rbRM, rbLB, rbBC, rbRB];
/* ã³ãŒããŒã©ãžãªãæä»éžæ / Select exactly one corner radio */
function selectCornerRb(target) {
for (var i = 0; i < allCornerRadios.length; i++) {
allCornerRadios[i].value = (allCornerRadios[i] === target);
}
}
selectCornerRb(rbLT);
addCornerKeyHandler(w);
/* æŽåã®åºæºã·ã§ãŒãã«ããïŒ1=ãã¹ãŠã®ã¢ãŒãããŒãã2=ã¢ã¯ãã£ããåºæº / Target shortcuts: 1=All Artboards, 2=Based on Active Artboard */
w.addEventListener("keydown", function (event) {
/* ããã¹ãå
¥åäžã¯æŽåã®åºæºã·ã§ãŒãã«ãããç¡å¹å / Skip alignment-base shortcuts while typing in edittext */
if (event.target && event.target.type === "edittext") return;
var k = event.keyName;
if (!k) return;
k = ("" + k).toLowerCase();
if (k === "1") {
rbTargetArtboard.value = true;
rbTargetSelection.value = false;
event.preventDefault();
updatePreviewFromUI();
} else if (k === "2") {
rbTargetSelection.value = true;
rbTargetArtboard.value = false;
event.preventDefault();
updatePreviewFromUI();
}
});
/* ã³ãŒããŒã©ãžãªçšã¯ãªãã¯ãã³ãã©ãäœæïŒ3è¡åãæç€ºçã«æä»åïŒ
Create a corner radio click handler and enforce mutual exclusion across the 3 rows */
function makeCornerClickHandler(rb) {
return function () {
selectCornerRb(rb);
updatePreviewFromUI();
};
}
for (var i = 0; i < allCornerRadios.length; i++) {
allCornerRadios[i].onClick = makeCornerClickHandler(allCornerRadios[i]);
}
rbTargetArtboard.onClick = updatePreviewFromUI;
rbTargetSelection.onClick = updatePreviewFromUI;
var pMargin = gRight.add("panel", undefined, _(LABELS.marginValue.ja, LABELS.marginValue.en) + " (" + unitLabel + ")");
pMargin.orientation = "row";
pMargin.alignChildren = ["fill", "center"];
pMargin.margins = [15, 20, 15, 10];
pMargin.helpTip = _(LABELS.marginTip.ja, LABELS.marginTip.en);
var leftColumn = pMargin.add("group");
leftColumn.orientation = "column";
leftColumn.alignChildren = ["left", "center"];
var rightColumn = pMargin.add("group");
rightColumn.orientation = "column";
rightColumn.alignChildren = ["left", "center"];
var gMX = leftColumn.add("group");
gMX.orientation = "row";
gMX.alignChildren = ["left", "center"];
gMX.add("statictext", undefined, _(LABELS.marginX.ja, LABELS.marginX.en));
var etMarginX = gMX.add("edittext", undefined, "0");
etMarginX.characters = 4;
var gMY = leftColumn.add("group");
gMY.orientation = "row";
gMY.alignChildren = ["left", "center"];
gMY.add("statictext", undefined, _(LABELS.marginY.ja, LABELS.marginY.en));
var etMarginY = gMY.add("edittext", undefined, "0");
etMarginY.characters = 4;
var cbLink = rightColumn.add("checkbox", undefined, _(LABELS.link.ja, LABELS.link.en));
cbLink.value = true;
cbLink.helpTip = _(LABELS.linkTip.ja, LABELS.linkTip.en);
/* å·Šå³ããŒãžã³å€æŽæã®åŠç / Handle horizontal margin edits */
function onMarginXEdit() {
if (cbLink.value) etMarginY.text = etMarginX.text;
updatePreviewFromUI();
}
/* äžäžããŒãžã³å€æŽæã®åŠç / Handle vertical margin edits */
function onMarginYEdit() {
if (!cbLink.value) updatePreviewFromUI();
}
etMarginX.onChange = etMarginX.onChanging = onMarginXEdit;
etMarginY.onChange = etMarginY.onChanging = onMarginYEdit;
changeValueByArrowKey(etMarginX, true, onMarginXEdit);
changeValueByArrowKey(etMarginY, true, onMarginYEdit);
/* Enter/Returnã§OKå®è¡ / Execute OK on Enter or Return */
function bindEnterToOK(editText) {
editText.addEventListener("keydown", function (ev) {
if (ev.keyName === "Enter" || ev.keyName === "Return") {
try { btnOK.notify(); } catch (eNotify) { }
ev.preventDefault();
}
});
}
/* ãã¬ãã¥ãŒå¢çãªãã·ã§ã³ / Preview bounds option */
var gOptions = w.add("group");
gOptions.orientation = "row";
gOptions.alignment = ["left", "top"];
gOptions.margins = [4, 4, 4, 4];
var cbUsePreviewBounds = gOptions.add("checkbox", undefined, _(LABELS.usePreviewBounds.ja, LABELS.usePreviewBounds.en));
cbUsePreviewBounds.value = usePreviewBounds;
cbUsePreviewBounds.helpTip = _(LABELS.usePreviewBoundsTip.ja, LABELS.usePreviewBoundsTip.en);
cbUsePreviewBounds.onClick = function () {
usePreviewBounds = cbUsePreviewBounds.value;
updatePreviewFromUI();
};
var gButtons = w.add("group");
gButtons.orientation = "row";
gButtons.alignChildren = ["center", "center"];
gButtons.alignment = ["center", "bottom"];
gButtons.add("button", undefined, _(LABELS.cancel.ja, LABELS.cancel.en), { name: "cancel" });
var btnOK = gButtons.add("button", undefined, _(LABELS.ok.ja, LABELS.ok.en), { name: "ok" });
try { w.defaultElement = btnOK; } catch (eDef) { }
bindEnterToOK(etMarginX);
bindEnterToOK(etMarginY);
/* é£åON/OFFæã®UIæŽæ° / Update UI when link mode changes */
function updateLinkStateUI() {
if (cbLink.value) {
/* é£åONïŒå·Šå³ãæäœå
ã«ãäžäžå
¥åãç¡å¹å / Linked ON: use horizontal as source and disable vertical input */
etMarginX.enabled = true;
etMarginY.enabled = false;
etMarginY.text = etMarginX.text;
} else {
/* é£åOFFïŒå·Šå³ã»äžäžãåå¥ã«æäœ / Linked OFF: edit horizontal and vertical independently */
etMarginX.enabled = true;
etMarginY.enabled = true;
}
updatePreviewFromUI();
}
cbLink.onClick = updateLinkStateUI;
/* ã¢ãŒãã«å¿ããŠæŽåå
ããã«ïŒããŒãžã³æ¬ã®æå¹ç¶æ
ãåæ
Sync enabled state of the corner panel, margin panel, and link checkbox */
function syncDialogEnabledState(targetIsSelection, isCenter) {
try { pCorner.enabled = !targetIsSelection; } catch (eDimCorner) { }
var enableMargin = (!isCenter && !targetIsSelection);
try { pMargin.enabled = enableMargin; } catch (eDim) { }
try { cbLink.enabled = enableMargin; } catch (eDim2) { }
}
/* å
¥åæ¬ããããŒãžã³ãptåäœã§ååŸïŒäžå€®ã»éžæã¢ãŒãæã¯0ïŒ
Read margin input as pt; use 0 in Center or Selection mode */
function readMarginPt(isCenter, targetIsSelection) {
if (isCenter || targetIsSelection) return { x: 0, y: 0 };
var mxInput = safeToNumber(etMarginX.text, 0);
var myInput = safeToNumber(etMarginY.text, 0);
var sourceY = cbLink.value ? mxInput : myInput;
var mxPt = toPt(mxInput, unitLabel);
var myPt = toPt(sourceY, unitLabel);
return { x: (mxPt === null ? 0 : mxPt), y: (myPt === null ? 0 : myPt) };
}
/* UIç¶æ
ãèªã¿åããæå¹ç¶æ
ã®åæãšãã¬ãã¥ãŒåæ ãå®è¡
Read UI state, sync enabled states, and update the preview */
function updatePreviewFromUI() {
var targetIsSelection = isTargetSelection();
var corner = getCornerFromUI();
var isCenter = (corner === "C");
syncDialogEnabledState(targetIsSelection, isCenter);
var margin = readMarginPt(isCenter, targetIsSelection);
applyPreview(doc, previewState, corner, margin.x, margin.y, targetIsSelection ? "selection" : "artboard");
}
/* ãã€ã¢ãã°çµäºæã¯ãã¬ãã¥ãŒãå·»ãæ»ãïŒOKåŸã¯mainã§ç¢ºå®å®è¡ïŒ / Revert preview on dialog close; OK is applied later in main() */
w.onClose = function () {
revertPreview(previewState, closingByOK ? false : true);
return true;
};
/* 衚瀺æã«å·Šå³ããŒãžã³æ¬ãžãã©ãŒã«ã¹ / Focus and select the horizontal margin field on show */
w.onShow = function () {
try {
etMarginX.active = true;
etMarginX.selection = [0, (etMarginX.text || "").length];
} catch (eFocus) { }
};
/* åæè¡šç€ºã§ãã¬ãã¥ãŒé©çšïŒéžæãããå ŽåïŒ / Apply initial preview when selection exists */
updateLinkStateUI();
btnOK.onClick = function () {
closingByOK = true;
revertPreview(previewState, false);
w.close(1);
};
if (w.show() !== 1) return null;
var corner = getCornerFromUI();
var isCenter = (corner === "C");
var targetIsSelection = isTargetSelection();
var marginPt = readMarginPt(isCenter, targetIsSelection);
return {
corner: corner,
targetMode: targetIsSelection ? "selection" : "artboard",
/* ãã¢ã¯ãã£ããåºæºããŸãã¯ãäžå€®ãã®ãšãã¯0ããã以å€ã¯{x, y} / 0 when selection mode or center; otherwise {x, y} */
marginPt: (isCenter || targetIsSelection) ? 0 : marginPt
};
}
/* æååãå®å
šã«æ°å€åãäžæ£å€ã¯ fallback / Safe string-to-number with fallback (default: null) */
function safeToNumber(s, fallback) {
if (fallback === undefined) fallback = null;
if (s === null || s === undefined) return fallback;
s = ("" + s).replace(/^\s+|\s+$/g, "");
if (s === "") return fallback;
var n = Number(s);
if (isNaN(n)) return fallback;
return n;
}
/* æ°å€å
¥åæ¬ãç¢å°ããŒã§å¢æžïŒShift=10ãOption=0.1ïŒ / Arrow-key increment for number fields */
function changeValueByArrowKey(editText, allowNegative, onValueChanged) {
if (allowNegative === undefined) allowNegative = false;
editText.addEventListener("keydown", function (event) {
/* Up / Down以å€ã¯çŽ éãïŒæ°å€å
¥åã劚ããªãïŒ / Pass through non-arrow keys */
if (event.keyName !== "Up" && event.keyName !== "Down") return;
var value = Number(editText.text);
if (isNaN(value)) value = 0;
var keyboard = ScriptUI.environment.keyboardState;
var direction = (event.keyName === "Up") ? 1 : -1;
if (keyboard.shiftKey) {
/* ShiftïŒ10ã®åæ°ã«ã¹ããã / Snap to multiples of 10 */
var step = 10;
value = (direction > 0)
? Math.ceil((value + 1) / step) * step
: Math.floor((value - 1) / step) * step;
} else if (keyboard.altKey) {
/* OptionïŒ0.1åäœ / Increment by 0.1 */
value = Math.round((value + direction * 0.1) * 10) / 10;
} else {
/* éåžžïŒ1åäœãæŽæ°äžžã / Default: by 1, integer */
value = Math.round(value + direction);
}
if (!allowNegative && value < 0) value = 0;
editText.text = value;
if (typeof onValueChanged === "function") {
try { onValueChanged(); } catch (eCb) { }
}
event.preventDefault();
});
}
// =========================================
// ã¢ãŒãããŒãæ¯ãåããšå€å® / Artboard mapping & predicates
// =========================================
/* éžæã¢ã€ãã ãäžå¿ç¹ãå±ããã¢ãŒãããŒãããšã«æ¯ãåã / Group selection by containing artboard (by center) */
function groupSelectedItemsByArtboard(doc, selection) {
var result = {};
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
if (isLockedOrHidden(item)) continue;
var itemBounds = getItemBounds(item); /* [å·Š, äž, å³, äž] / [L, T, R, B] */
if (!itemBounds) continue;
var cx = (itemBounds[0] + itemBounds[2]) / 2;
var cy = (itemBounds[1] + itemBounds[3]) / 2;
var abIndex = findArtboardIndexByPoint(doc, cx, cy);
if (abIndex === -1) continue;
if (!result[abIndex]) result[abIndex] = [];
result[abIndex].push(item);
}
return result;
}
/* 座æš(x,y)ãå«ãã¢ãŒãããŒãã®ã€ã³ããã¯ã¹ãè¿ã / Return index of artboard containing (x, y) */
function findArtboardIndexByPoint(doc, x, y) {
var n = doc.artboards.length;
for (var i = 0; i < n; i++) {
var r = doc.artboards[i].artboardRect; /* [å·Š, äž, å³, äž] / [L, T, R, B] */
if (x >= r[0] && x <= r[2] && y <= r[1] && y >= r[3]) return i;
}
return -1;
}
/* ã¢ã€ãã ãŸãã¯èŠªéå±€ãããã¯/é衚瀺ãå€å® / Check if item or any ancestor is locked/hidden */
function isLockedOrHidden(item) {
try { if (item.locked) return true; } catch (e) { }
try { if (item.hidden) return true; } catch (e2) { }
var p = item.parent;
while (p) {
try { if (p.locked) return true; } catch (e3) { }
try { if (p.hidden) return true; } catch (e4) { }
if (p.typename === "Document") break;
p = p.parent;
}
return false;
}
/* è€æ°ã¢ã€ãã ãå
å«ããæå°ããŠã³ãã£ã³ã°ãè¿ã / Return union bounds of multiple items */
function getUnionBounds(items) {
if (!items || items.length === 0) return null;
var l = null, t = null, r = null, b = null;
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (!item) continue;
var itemBounds = getItemBounds(item);
if (!itemBounds) continue;
if (l === null) {
l = itemBounds[0]; t = itemBounds[1]; r = itemBounds[2]; b = itemBounds[3];
} else {
if (itemBounds[0] < l) l = itemBounds[0];
if (itemBounds[1] > t) t = itemBounds[1];
if (itemBounds[2] > r) r = itemBounds[2];
if (itemBounds[3] < b) b = itemBounds[3];
}
}
if (l === null) return null;
return [l, t, r, b];
}
// =========================================
// æŽååŠç / Alignment
// =========================================
/* æŽåå
ã¢ã³ã«ãŒã®ã¢ãŒãããŒãäžã®åº§æšãèšç® / Compute target anchor point on the artboard */
function computeCornerTargetPoint(artboardRect, corner, marginX, marginY) {
var abL = artboardRect[0];
var abT = artboardRect[1];
var abR = artboardRect[2];
var abB = artboardRect[3];
var abCx = (abL + abR) / 2;
var abCy = (abT + abB) / 2;
if (corner === "LT") return [abL + marginX, abT - marginY];
if (corner === "TC") return [abCx, abT - marginY];
if (corner === "RT") return [abR - marginX, abT - marginY];
if (corner === "LM") return [abL + marginX, abCy];
if (corner === "C") return [abCx, abCy];
if (corner === "RM") return [abR - marginX, abCy];
if (corner === "LB") return [abL + marginX, abB + marginY];
if (corner === "BC") return [abCx, abB + marginY];
return [abR - marginX, abB + marginY]; /* å³äž / RB */
}
/* åã¢ã€ãã ãã¢ãŒãããŒãåºæºã®ã¢ã³ã«ãŒãžæŽåïŒããŒãžã³ä»ãïŒ / Align each item to artboard anchor with margin */
function alignItemsToCornerWithMargin(items, artboardRect, corner, margin) {
var marginXY = normalizeMarginXY(margin);
alignItemsToCornerWithMarginCore(
items,
artboardRect,
corner,
marginXY.x,
marginXY.y,
translateItemDirect
);
}
/* ããŒãžã³æå®ã {x, y} 圢åŒãžæ£èŠå / Normalize margin value to {x, y} */
function normalizeMarginXY(margin) {
if (typeof margin === "object" && margin !== null) {
return {
x: margin.x || 0,
y: margin.y || 0
};
}
return {
x: margin || 0,
y: margin || 0
};
}
/* æŽååŠçã®å
±éæ¬äœ / Shared item alignment core */
function alignItemsToCornerWithMarginCore(items, artboardRect, corner, marginX, marginY, translateItemForAlignment) {
var target = computeCornerTargetPoint(artboardRect, corner, marginX, marginY);
var targetX = target[0];
var targetY = target[1];
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (!item) continue;
var itemBounds = getItemBounds(item);
if (!itemBounds) continue;
var anchor = getBoundsAnchorPoint(itemBounds, corner);
var dx = targetX - anchor[0];
var dy = targetY - anchor[1];
translateItemForAlignment(item, dx, dy);
}
}
/* ã¢ã€ãã ãçŽæ¥ç§»å / Translate item directly */
function translateItemDirect(item, dx, dy) {
try { item.translate(dx, dy); } catch (e) { }
}
/* ãã¬ãã¥ãŒçšïŒç§»åéãèšé²ããªããæŽåïŒåŸã§å·»ãæ»ãå¯èœïŒ / Preview alignment with recorded deltas for later revert */
function alignItemsToCornerWithMarginPreviewXY(items, artboardRect, corner, marginX, marginY, previewState) {
alignItemsToCornerWithMarginCore(
items,
artboardRect,
corner,
marginX,
marginY,
function (item, dx, dy) {
translateItemForPreview(item, dx, dy, previewState);
}
);
}
/* ãã¬ãã¥ãŒçšïŒã¢ã€ãã ãç§»åããŠç§»åéãèšé² / Translate an item and record its preview delta */
function translateItemForPreview(item, dx, dy, previewState) {
var itemIndex = findPreviewItemIndex(previewState, item);
try { item.translate(dx, dy); } catch (e) { }
if (itemIndex >= 0) {
previewState.dx[itemIndex] += dx;
previewState.dy[itemIndex] += dy;
}
}
/* ãã¬ãã¥ãŒç¶æ
å
ã®ã¢ã€ãã äœçœ®ãæ€çŽ¢ / Find the item index in preview state */
function findPreviewItemIndex(previewState, targetItem) {
if (!previewState || !previewState.items) return -1;
for (var i = 0; i < previewState.items.length; i++) {
if (previewState.items[i] === targetItem) return i;
}
return -1;
}
/* ã¢ãŒãããŒãç©åœ¢äžã®9ç¹ã¢ã³ã«ãŒåº§æšãè¿ãïŒããŒãžã³ãªãïŒ / Return one of the 9 artboard anchor points without margin */
function getArtboardAnchorPoint(artboardRect, corner) {
return computeCornerTargetPoint(artboardRect, corner, 0, 0);
}
/* ããŠã³ãã£ã³ã°ããã¯ã¹äžã®9ç¹ã¢ã³ã«ãŒåº§æšãè¿ã / Return one of the 9 bounds anchor points */
function getBoundsAnchorPoint(bounds, corner) {
/* bounds: [å·Š, äž, å³, äž] / [L, T, R, B] */
var l = bounds[0], t = bounds[1], r = bounds[2], b = bounds[3];
var cx = (l + r) / 2;
var cy = (t + b) / 2;
if (corner === "C") return [cx, cy];
if (corner === "LT") return [l, t];
if (corner === "TC") return [cx, t];
if (corner === "RT") return [r, t];
if (corner === "LM") return [l, cy];
if (corner === "RM") return [r, cy];
if (corner === "LB") return [l, b];
if (corner === "BC") return [cx, b];
return [r, b]; /* RB */
}
/* ã¢ã¯ãã£ãã¢ãŒãããŒãäžã®éžæãåºæºã«ä»ã¢ãŒãããŒããžæŽå / Align other artboards by active-artboard reference */
function alignByActiveArtboardReference(doc, sourceItems, corner, moveGroupWithOffset) {
var activeArtboardIndex = -1;
try { activeArtboardIndex = doc.artboards.getActiveArtboardIndex(); } catch (e) { activeArtboardIndex = -1; }
if (activeArtboardIndex < 0) return;
var itemsByArtboard = groupSelectedItemsByArtboard(doc, sourceItems);
if (!itemsByArtboard) return;
var referenceItems = itemsByArtboard[activeArtboardIndex];
if (!referenceItems || referenceItems.length === 0) return;
var referenceRect = doc.artboards[activeArtboardIndex].artboardRect;
var offset = computeGroupOffsetFromArtboard(referenceItems, referenceRect, corner);
if (!offset) return;
for (var artboardIndex in itemsByArtboard) {
if (!itemsByArtboard.hasOwnProperty(artboardIndex)) continue;
var targetArtboardIndex = parseInt(artboardIndex, 10);
if (targetArtboardIndex === activeArtboardIndex) continue;
var targetItems = itemsByArtboard[artboardIndex];
if (!targetItems || targetItems.length === 0) continue;
var targetRect = doc.artboards[targetArtboardIndex].artboardRect;
moveGroupWithOffset(targetItems, targetRect, corner, offset);
}
}
/* ãã³ãã¬çŸ€ãšã¢ãŒãããŒãã¢ã³ã«ãŒã®çžå¯Ÿãªãã»ãããèšç® / Compute relative offset of template group from artboard anchor */
function computeGroupOffsetFromArtboard(items, artboardRect, corner) {
/* æ»ãå€ïŒ{x, y} = groupAnchor - artboardAnchor / Returns {x, y} offset */
var groupBounds = getUnionBounds(items);
if (!groupBounds) return null;
var artboardAnchor = getArtboardAnchorPoint(artboardRect, corner);
var groupAnchor = getBoundsAnchorPoint(groupBounds, corner);
return { x: (groupAnchor[0] - artboardAnchor[0]), y: (groupAnchor[1] - artboardAnchor[1]) };
}
/* ã¢ã€ãã 矀ããªãã»ããä»ãã§ã¢ãŒãããŒãã¢ã³ã«ãŒã«æŽå / Align a group to the artboard anchor with an offset */
function alignGroupToArtboardWithOffset(items, artboardRect, corner, offset) {
var groupBounds = getUnionBounds(items);
if (!groupBounds) return;
var artboardAnchor = getArtboardAnchorPoint(artboardRect, corner);
var groupAnchor = getBoundsAnchorPoint(groupBounds, corner);
var dx = artboardAnchor[0] + (offset.x || 0) - groupAnchor[0];
var dy = artboardAnchor[1] + (offset.y || 0) - groupAnchor[1];
for (var i = 0; i < items.length; i++) {
try { items[i].translate(dx, dy); } catch (e) { }
}
}
/* ãã¬ãã¥ãŒçšïŒã¢ã€ãã çŸ€ãæŽåããç§»åéãèšé² / Preview group alignment with recorded deltas for later revert */
function alignGroupToArtboardWithOffsetPreview(items, artboardRect, corner, offset, previewState) {
var groupBounds = getUnionBounds(items);
if (!groupBounds) return;
var artboardAnchor = getArtboardAnchorPoint(artboardRect, corner);
var groupAnchor = getBoundsAnchorPoint(groupBounds, corner);
var dx = artboardAnchor[0] + (offset.x || 0) - groupAnchor[0];
var dy = artboardAnchor[1] + (offset.y || 0) - groupAnchor[1];
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (!item) continue;
translateItemForPreview(item, dx, dy, previewState);
}
}ã¢ãŒãããŒãåäœã§ã¬ã³ãŒããæµã蟌ãã¹ã¯ãªãã
#target illustrator
app.preferences.setBooleanPreference('ShowExternalJSXWarning', false);
/*
VariableDataImport.jsx
æŠèŠ / Overview:
CSV / ã¿ãåºåãããã¹ã ã®ããŒã¿ãã¡ã€ã«ã Illustrator ã®ãã³ãã¬ãŒãã«æµã蟌ãããŒã¿çµåã¹ã¯ãªããã
ããã¹ããã¬ãŒã å
ã® <ããããŒå> 圢åŒã®ã¿ã°ãããŒã¿å€ã«çœ®æãã
ããŒã¿è¡æ°ã¶ãã®ã¢ãŒãããŒããšããªãšãŒã·ã§ã³ãçæããã
A data-merge script for Illustrator. It imports a CSV / TSV data file,
replaces <header> placeholder tags inside text frames with row values,
and generates one artboard variation per data row.
äž»ãªåäœ / Behavior:
- ããŒã¿ãã¡ã€ã«ã¯ãéããŠããããã¥ã¡ã³ããšåããã©ã«ããŒã® .csv / .txt ããéžã¶ã
- å®è¡æã«å
ããã¥ã¡ã³ããå¥åä¿åã§è€è£œããè€è£œåŽã«æµã蟌ãïŒå
ãã¡ã€ã«ã¯ç¡å€æŽïŒã
- ã¢ãŒãããŒã0ãé圢ãšããããŒã¿ä»¶æ°ã¶ãã¢ãŒãããŒããè€è£œããã
æ£æ¹åœ¢ã«è¿ãã°ãªãããèšç®ããã«ã³ãã¹ã®å€©å°ã»å·Šå³äžå€®ã«é
眮ããã
- ã¢ãŒãããŒãåã¯ãéžæããããŒã¿åã®å€ããèšå®ããã
- ããã¬ãã¥ãŒãããªã³ã«ãããšãå
ãã¡ã€ã«ã倿Žããè€è£œãã¡ã€ã«ã§çµæã確èªã§ããã
èšå®å€æŽæã¯å
ããã¥ã¡ã³ããããã¬ãã¥ãŒçšãã¡ã€ã«ãäœãçŽããŠåæ ããã
ããã¬ãã¥ãŒãããªãã«ãããšãéããŠãããã¬ãã¥ãŒçšããã¥ã¡ã³ããä¿åããéããã
- 1ä»¶ç®ã®ããŒã¿ãæåŸã«åŠçããé圢ã®ã¿ã°æ¶å€±ãåé¿ããã
*/
// =========================================
// ããŒãžã§ã³ãšããŒã«ã©ã€ãº / Version & Localization
// =========================================
var SCRIPT_VERSION = "v1.4";
/* å®è¡ç°å¢ã®ãã±ãŒã«ãã衚瀺èšèªãå€å® / Detect the display language from the runtime locale */
function getCurrentLang() {
return ($.locale.indexOf("ja") === 0) ? "ja" : "en";
}
var lang = getCurrentLang();
/* æ¥è±ã©ãã«å®çŸ© / Japanese-English label definitions */
var LABELS = {
dialogTitle: { ja: "ããŒã¿æµã蟌ã¿", en: "Data Import" },
infoTitle: { ja: "ããŒã¿ãã¡ã€ã«", en: "Data File" },
fileLabel: { ja: "ãã¡ã€ã«", en: "File" },
settingsTitle: { ja: "æµã蟌ã¿èšå®", en: "Import Settings" },
abNameLabel: { ja: "ã¢ãŒãããŒãåã®åç
§å", en: "Artboard name column" },
preview: { ja: "ãã¬ãã¥ãŒ", en: "Preview" },
cancel: { ja: "ãã£ã³ã»ã«", en: "Cancel" },
run: { ja: "å®è¡", en: "Run" },
processing: { ja: "åŠçäž...", en: "Processing..." },
done: { ja: "å®äºïŒ\n#count# ä»¶åŠçããŸããã", en: "Done!\nProcessed #count # rows." },
noDoc: { ja: "ããã¥ã¡ã³ããéãããŠããŸããã", en: "No document is open." },
needSave: { ja: "ããã¥ã¡ã³ããä¿åããŠããå®è¡ããŠãã ããã", en: "Please save the document before running." },
noDataFiles: { ja: "åãéå±€ã«.txtãŸãã¯.csvãã¡ã€ã«ãèŠã€ãããŸããã§ããã", en: "No .txt or .csv files found in the same folder." },
noTemplate: { ja: "é圢ã«ãªããžã§ã¯ãããããŸããã", en: "No template objects found." },
dupFailed: { ja: "ããã¥ã¡ã³ãã®è€è£œïŒå¥åä¿åïŒã«å€±æããŸããã\n\n#detail#", en: "Failed to duplicate (Save As) the document.\n\n#detail#" },
tooManyData: { ja: "ããŒã¿ä»¶æ°ïŒ#count# ä»¶ïŒãã«ã³ãã¹ã«åãŸããŸããã\nçŸåšã®èšå®ã§ã¯æå€§ #max # ä»¶ãŸã§é
眮ã§ããŸãã\nééãå°ããããŠãã ããã", en: "The number of rows (#count#) does not fit on the canvas.\nUp to #max # artboards can be placed with the current settings.\nReduce the gap." },
gapLabel: { ja: "ã¢ãŒãããŒãéé", en: "Artboard gap" },
fileHelp: { ja: "éããŠããããã¥ã¡ã³ããšåããã©ã«ããŒã«ãã CSV / TSV ãã¡ã€ã«ãéžã³ãŸãã", en: "Choose a CSV / TSV file in the same folder as the open document." },
artboardNameHelp: { ja: "åã¢ãŒãããŒãåã«äœ¿ãããŒã¿åãéžã³ãŸãã", en: "Choose the data column used for each artboard name." },
gapHelp: { ja: "è€è£œããã¢ãŒãããŒãå士ã®ééã§ããå
¥åå€ã¯10ptåäœã«äžžããããŸãã", en: "The gap between duplicated artboards. Values are rounded to 10 pt increments." },
previewHelp: { ja: "å
ãã¡ã€ã«ã倿Žãããè€è£œãã¡ã€ã«ã§æµã蟌ã¿çµæã確èªããŸãã", en: "Preview the import result in a duplicate file without changing the original." },
runHelp: { ja: "å
ããã¥ã¡ã³ããå¥åä¿åã§è€è£œããè€è£œåŽã«ããŒã¿ãæµã蟌ã¿ãŸãã", en: "Duplicate the original document with Save As and import the data into the copy." },
emptyFile: { ja: "éžæãããã¡ã€ã«ã«ããããŒè¡ããããŸããã", en: "The selected file has no header row." },
fileOpenFailed: { ja: "éžæãããã¡ã€ã«ãéããŸããã§ããã", en: "Could not open the selected file." }
};
/* ããŒããçŸåšã®èšèªã®ã©ãã«ãååŸïŒç¡ããã°ããŒåããã®ãŸãŸè¿ãïŒ/ Get the localized label for a key (falls back to the key itself) */
function L(key) {
try {
if (LABELS[key] && LABELS[key][lang]) return LABELS[key][lang];
} catch (e) { }
return key;
}
/* ã³ãã³ä»ãã©ãã«ïŒæ¥æ¬èªã¯å
šè§ãè±èªã¯åè§ïŒ/ Label with a colon (full-width for JA, half-width for EN) */
function labelText(key) {
return L(key) + (lang === "ja" ? "ïŒ" : ":");
}
/* æååå
é ã®BOMïŒU+FEFF / 65279ïŒãšååŸã®ç©ºçœãé€å» / Strip a leading BOM (U+FEFF / 65279) and surrounding whitespace */
function trimAndStripBom(text) {
text = String(text);
if (text.length && text.charCodeAt(0) === 65279) text = text.substring(1);
return text.replace(/^\s+|\s+$/g, "");
}
(function () {
var dataRows = []; // èªã¿èŸŒãã ããŒã¿è¡ / Loaded data rows
var headers = []; // ããããŒïŒååïŒ/ Header column names
var previewFile = null; // ãã¬ãã¥ãŒçšã«éãè€è£œãã¡ã€ã« / Duplicate file opened for preview
// =========================================
// åæãã§ãã¯ãšããŒã¿ãã¡ã€ã«åé / Initial checks & data file discovery
// =========================================
if (app.documents.length === 0) {
alert(L("noDoc"));
return;
}
var doc = app.activeDocument;
var docPath;
try {
docPath = doc.path;
} catch (e) {
alert(L("needSave"));
return;
}
var documentFolder = new Folder(docPath);
var dataFiles = documentFolder.getFiles(/\.(txt|csv)$/i);
if (dataFiles.length === 0) {
alert(L("noDataFiles"));
return;
}
/* ã«ã³ãã¹ç¯å²ãšé圢ã¢ãŒãããŒãã®ãµã€ãºãååŸ / Canvas bounds & template artboard size */
var MAX_ARTBOARDS = 1000;
var canvasBounds = getCanvasBounds();
var templateRect = doc.artboards[0].artboardRect;
var templateWidth = templateRect[2] - templateRect[0];
var templateHeight = templateRect[1] - templateRect[3];
// =========================================
// ãã€ã¢ãã°UIã®æ§ç¯ / Build the dialog UI
// =========================================
var LABEL_WIDTH = (lang === "ja") ? 165 : 195; // æµã蟌ã¿èšå®ããã«ã®ã©ãã«å¹
/ Label width in the import-settings panel
/* èšå®ããã«çšïŒäžå®å¹
ã®ã³ãã³ä»ãã©ãã«ã远å ããé
ç®ãçžŠã«æãã / Add a fixed-width colon label so settings rows line up */
function addFieldLabel(parentGroup, key) {
var labelControl = parentGroup.add("statictext", undefined, labelText(key));
labelControl.preferredSize.width = LABEL_WIDTH;
return labelControl;
}
var mainDialog = new Window("dialog", L("dialogTitle") + " " + SCRIPT_VERSION);
mainDialog.orientation = "column";
mainDialog.alignChildren = ["fill", "top"];
mainDialog.spacing = 10;
mainDialog.margins = 15;
/* ããŒã¿ãã¡ã€ã«ããã«ïŒãã¡ã€ã«éžæãšããŒã¿ãã¬ãã¥ãŒ / Data-file panel: file selector & data preview */
var infoPanel = mainDialog.add("panel", undefined, L("infoTitle"));
infoPanel.orientation = "column";
infoPanel.alignChildren = ["fill", "top"];
infoPanel.margins = 15;
infoPanel.spacing = 10;
var fileSelectGroup = infoPanel.add("group");
fileSelectGroup.add("statictext", undefined, labelText("fileLabel"));
var fileDropdown = fileSelectGroup.add("dropdownlist", undefined, []);
fileDropdown.size = [350, 25];
fileDropdown.helpTip = L("fileHelp");
for (var i = 0; i < dataFiles.length; i++) fileDropdown.add("item", decodeURI(dataFiles[i].name));
var listContainer = infoPanel.add("group");
listContainer.alignment = ["fill", "fill"];
var dataListBox = null;
var settingsPanel = mainDialog.add("panel", undefined, L("settingsTitle"));
settingsPanel.orientation = "column";
settingsPanel.alignChildren = ["left", "top"];
settingsPanel.margins = 15;
var artboardNameGroup = settingsPanel.add("group");
addFieldLabel(artboardNameGroup, "abNameLabel");
var artboardNameDropdown = artboardNameGroup.add("dropdownlist", undefined, []);
artboardNameDropdown.size = [200, 25];
artboardNameDropdown.helpTip = L("artboardNameHelp");
/* ã°ãªããé
眮èšå®ïŒã¢ãŒãããŒãééïŒ/ Grid layout settings (artboard gap) */
var defaultGap = Math.round(templateWidth / 5 / 10) * 10;
var rowGap = settingsPanel.add("group");
addFieldLabel(rowGap, "gapLabel");
var gapInput = rowGap.add("edittext", undefined, String(defaultGap));
gapInput.size = [60, 25];
gapInput.helpTip = L("gapHelp");
rowGap.add("statictext", undefined, "pt");
// =========================================
// ã°ãªããé
眮ã®èšç® / Grid layout calculations
// =========================================
/* 暪æ¹åã«äžŠã¹ãããæå€§æ°ïŒã«ã³ãã¹å¹
ããç®åºïŒ / Max columns by canvas width */
function calcMaxColumns(gapSize) {
var availableWidth = canvasBounds[2] - canvasBounds[0];
var maxCount = Math.floor((availableWidth - templateWidth) / (gapSize + templateWidth)) + 1;
return (maxCount < 1) ? 1 : maxCount;
}
/* 瞊æ¹åã«äžŠã¹ãããæå€§æ°ïŒã«ã³ãã¹é«ãããç®åºïŒ / Max rows by canvas height */
function calcMaxRows(gapSize) {
var availableHeight = canvasBounds[1] - canvasBounds[3];
var maxCount = Math.floor((availableHeight - templateHeight) / (gapSize + templateHeight)) + 1;
return (maxCount < 1) ? 1 : maxCount;
}
/* ã¢ãŒãããŒãééã®å
¥åå€ãååŸïŒè² å€ã¯0ã«è£æ£ãã10ã®åæ°ãžåæšäºå
¥ïŒ/ Read the gap input (clamp negatives to 0, round to the nearest multiple of 10) */
function getGapValue() {
var gap = parseFloat(gapInput.text);
if (isNaN(gap) || gap < 0) gap = 0;
return Math.round(gap / 10) * 10;
}
/*
ã¢ãŒãããŒãã®ã°ãªãããç®åº / Resolve the artboard grid.
ã°ãªããå
šäœã®å¹
ãšé«ãããªãã¹ãçããïŒæ£æ¹åœ¢ã«è¿ãïŒãªãåæ°ãéžã³ã
ã«ã³ãã¹ã®å€©å°ã»å·Šå³äžå€®ã«é
眮ããã
*/
function computeArtboardLayout() {
var gap = getGapValue();
var maxFitColumns = calcMaxColumns(gap); // 暪ã«åãŸãæå€§åæ° / max columns that fit
var maxFitRows = calcMaxRows(gap); // 瞊ã«åãŸãæå€§è¡æ° / max rows that fit
var dataCount = dataRows ? dataRows.length : 0;
var layout = { cols: maxFitColumns, rows: 0, gap: gap, fits: false };
if (dataCount < 1) return layout; // æªèªèŸŒïŒè¡šç€ºçšã«æå€§åæ°ãè¿ã
var bestColumns = 0, smallestDiff = -1;
for (var columns = 1; columns <= maxFitColumns; columns++) {
var rows = Math.ceil(dataCount / columns);
if (rows > maxFitRows) continue; // 瞊ã«åãŸããªã
if (columns * rows > MAX_ARTBOARDS) continue; // ã¢ãŒãããŒãæ°ã®äžé
var occupiedColumns = (columns < dataCount) ? columns : dataCount; // å®éã«äœ¿ãåæ°
var gridWidth = occupiedColumns * templateWidth + (occupiedColumns - 1) * gap;
var gridHeight = rows * templateHeight + (rows - 1) * gap;
var widthHeightDiff = Math.abs(gridWidth - gridHeight);
if (smallestDiff < 0 || widthHeightDiff < smallestDiff) {
smallestDiff = widthHeightDiff;
bestColumns = columns;
}
}
if (bestColumns < 1) return layout; // ã©ã®åæ°ã§ãåãŸããªãïŒfits:falseïŒ
layout.cols = bestColumns;
layout.rows = Math.ceil(dataCount / bestColumns);
layout.fits = true;
return layout;
}
/* å
¥åç¢ºå®æã«ééã10ã®åæ°ãžåæšäºå
¥ããå
¥åæ¬ãžåæ / On commit, round the gap to the nearest 10 and write it back to the field */
function roundGapInput() {
gapInput.text = String(getGapValue());
}
gapInput.onChange = function () {
roundGapInput();
if (previewCheckbox.value) runPreview(); // ãã¬ãã¥ãŒäžãªãè€è£œãã¡ã€ã«ãéãçŽããŠæŽæ° / refresh the preview while active
};
// ãã¿ã³ãšãªã¢ïŒ3ã«ã©ã ïŒå·ŠïŒãã¬ãã¥ãŒ / äžå€®ïŒã¹ããŒãµãŒ / å³ïŒãã£ã³ã»ã«ã»å®è¡ïŒ
var buttonArea = mainDialog.add("group");
buttonArea.orientation = "row";
buttonArea.alignment = ["fill", "top"];
var buttonAreaLeft = buttonArea.add("group");
buttonAreaLeft.alignment = ["left", "center"];
var previewCheckbox = buttonAreaLeft.add("checkbox", undefined, L("preview"));
previewCheckbox.helpTip = L("previewHelp");
var buttonAreaCenter = buttonArea.add("group"); // äžå€®ã¹ããŒãµãŒïŒäŒžçž®ïŒ/ flexible spacer
buttonAreaCenter.alignment = ["fill", "center"];
var buttonAreaRight = buttonArea.add("group");
buttonAreaRight.alignment = ["right", "center"];
var cancelButton = buttonAreaRight.add("button", undefined, L("cancel"), { name: "cancel" });
var runButton = buttonAreaRight.add("button", undefined, L("run"), { name: "ok" });
runButton.helpTip = L("runHelp");
// =========================================
// ããã¥ã¡ã³ãã®è€è£œïŒå¥åä¿åïŒ/ Document duplication (Save As)
// =========================================
/* è€è£œãã¡ã€ã«ã®ãã¹ãçæïŒå
å_ã¿ã°_æ¥æ.æ¡åŒµåïŒ/ Build the duplicate file path (origName_tag_timestamp.ext) */
function buildDuplicateFilePath(originalFile, tag) {
var now = new Date();
function padTwoDigits(num) { return (num < 10 ? "0" : "") + String(num); }
var timestamp = String(now.getFullYear()) + padTwoDigits(now.getMonth() + 1) + padTwoDigits(now.getDate()) + "_" + padTwoDigits(now.getHours()) + padTwoDigits(now.getMinutes()) + padTwoDigits(now.getSeconds());
var parentFolder = originalFile.parent;
var originalName = originalFile.name;
var dotIndex = originalName.lastIndexOf(".");
var baseName = (dotIndex >= 0) ? originalName.substring(0, dotIndex) : originalName;
var extension = (dotIndex >= 0) ? originalName.substring(dotIndex) : ".ai";
var duplicateName = baseName + "_" + (tag || "import") + "_" + timestamp + extension;
return new File(parentFolder.fsName + "/" + duplicateName);
}
/* æå®ããã¥ã¡ã³ããå¥åä¿åããæäœå¯Ÿè±¡ãšããŠè€è£œåŸããã¥ã¡ã³ããè¿ã / Save the document under a new name and return the duplicated document */
function duplicateDocumentBySaveAs(sourceDocument) {
var originalFile = sourceDocument.fullName; // File
var duplicateFile = buildDuplicateFilePath(originalFile);
sourceDocument.saveAs(duplicateFile); // Illustrator switches this document to the duplicated file
return sourceDocument;
}
// =========================================
// CSV / TSV ã®è§£æãšèªã¿èŸŒã¿ / CSV / TSV parsing & loading
// =========================================
/* 1è¡ãåºåãæåã§åå²ïŒCSVã¯åŒçšç¬Šã»ãšã¹ã±ãŒããè§£éïŒ/ Split one line by delimiter (CSV also honors quotes and escapes) */
function parseLine(line, delimiter) {
if (delimiter === "\t") return line.split("\t");
var fields = [], pattern = new RegExp("(\\" + delimiter + "|\\r?\\n|\\r|^)(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|([^\"\\" + delimiter + "\\r\\n]*))", "gi");
var matches = null;
while (matches = pattern.exec(line)) {
fields.push(matches[2] ? matches[2].replace(/\"\"/g, "\"") : matches[3]);
}
return fields;
}
/* Illustrator ã®æå€§ã«ã³ãã¹ç¯å²ãååŸïŒäžæã¬ã€ã€ãŒã§åç¹ã枬å®ïŒ/ Get Illustrator's max canvas bounds (measures the origin via a temp layer) */
function getCanvasBounds() {
var CANVAS_MAX_SIZE = 16383;
var targetDoc = app.activeDocument;
var wasModified = targetDoc.modified; // èšæž¬åã®å€æŽãã©ã°ãéé¿ / remember the modified flag before measuring
var tempLayer = targetDoc.layers.add();
var tempTextFrame = tempLayer.textFrames.add();
var left = tempTextFrame.matrix.mValueTX;
var top = tempTextFrame.matrix.mValueTY;
tempLayer.remove();
targetDoc.modified = wasModified; // äžæã¬ã€ã€ãŒè¿œå ã§ç«ã£ã倿Žãã©ã°ãå
ã«æ»ã / restore the modified flag
// [left, top, right, bottom]
return [left, top, left + CANVAS_MAX_SIZE, top - CANVAS_MAX_SIZE];
}
/* éžæãã¡ã€ã«ãèªã¿èŸŒã¿ãããããŒã»ããŒã¿ã»ããŒã¿ãªã¹ããåæ§ç¯ / Load the selected file and rebuild headers, rows and the data list */
function loadDataFile(dataFile) {
if (dataListBox !== null) { listContainer.remove(dataListBox); dataListBox = null; }
dataRows = [];
dataFile.encoding = "UTF-8";
if (!dataFile.open("r")) {
headers = [];
artboardNameDropdown.removeAll();
mainDialog.layout.layout(true);
alert(L("fileOpenFailed"));
return;
}
var fileContent = dataFile.read();
dataFile.close();
var lines = fileContent.split(/[\r\n]+/);
if (lines.length === 0) return;
var delimiter = dataFile.name.toLowerCase().match(/\.csv$/) ? "," : "\t";
headers = parseLine(lines[0], delimiter);
// ããããŒã®æ£èŠåïŒBOM/ååŸç©ºçœãé€å»ïŒ/ Normalize headers (strip BOM & surrounding spaces)
for (var headerIndex = 0; headerIndex < headers.length; headerIndex++) {
headers[headerIndex] = trimAndStripBom(headers[headerIndex]);
}
// ããããŒãå®è³ªç©ºïŒç©ºãã¡ã€ã«çïŒãªãäžæ / Abort when there is effectively no header (e.g. empty file)
var hasHeader = false;
for (var headerCheckIndex = 0; headerCheckIndex < headers.length; headerCheckIndex++) {
if (headers[headerCheckIndex] !== "") { hasHeader = true; break; }
}
if (!hasHeader) {
headers = [];
artboardNameDropdown.removeAll();
mainDialog.layout.layout(true);
alert(L("emptyFile"));
return;
}
artboardNameDropdown.removeAll();
for (var dropdownHeaderIndex = 0; dropdownHeaderIndex < headers.length; dropdownHeaderIndex++) {
artboardNameDropdown.add("item", headers[dropdownHeaderIndex]);
}
artboardNameDropdown.selection = 0;
dataListBox = listContainer.add("listbox", [0, 0, 550, 180], [], {
numberOfColumns: headers.length, showHeaders: true, columnTitles: headers
});
for (var lineIndex = 1; lineIndex < lines.length; lineIndex++) {
if (lines[lineIndex] === "") continue;
var cells = parseLine(lines[lineIndex], delimiter);
// å€ã®æ£èŠåïŒååŸç©ºçœãé€å»ïŒ/ Normalize cell values (strip surrounding spaces)
for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) {
cells[cellIndex] = String(cells[cellIndex]).replace(/^\s+|\s+$/g, "");
}
dataRows.push(cells);
var listItem = dataListBox.add("item", cells[0] || "");
for (var listCellIndex = 1; listCellIndex < cells.length; listCellIndex++) {
if (listCellIndex < headers.length) {
listItem.subItems[listCellIndex - 1].text = cells[listCellIndex] || "";
}
}
}
mainDialog.layout.layout(true);
}
fileDropdown.onChange = function () {
if (fileDropdown.selection) loadDataFile(dataFiles[fileDropdown.selection.index]);
};
fileDropdown.selection = 0;
// =========================================
// å®è¡åŠçïŒæµã蟌ã¿ïŒ/ Run handler (data import)
// =========================================
/* é
眮ã¬ã€ã¢ãŠãã確å®ïŒåãŸããªããã°èŠåã㊠null ãè¿ãïŒ/ Resolve the layout (alerts and returns null when it does not fit) */
function prepareLayout() {
var nameColumnIndex = artboardNameDropdown.selection ? artboardNameDropdown.selection.index : 0;
var gridLayout = computeArtboardLayout();
if (!gridLayout.fits) {
var maxFitColumns = calcMaxColumns(gridLayout.gap);
var maxCapacity = Math.min(maxFitColumns * calcMaxRows(gridLayout.gap), MAX_ARTBOARDS);
alert(L("tooManyData").replace("#count#", String(dataRows.length)).replace("#max#", String(maxCapacity)));
return null;
}
return {
cols: gridLayout.cols,
rows: gridLayout.rows,
gap: gridLayout.gap,
nameColumnIndex: nameColumnIndex
};
}
/* é圢ãè€è£œããŠããŒã¿ãæµã蟌ãïŒtargetDoc ã«å¯ŸããŠå®è¡ïŒ/ Duplicate the template and merge data into targetDoc */
function performImport(targetDoc, layout, isPreview) {
targetDoc.activate();
var nameColumnIndex = layout.nameColumnIndex;
var columnCount = layout.cols;
var gap = layout.gap;
var progressWindow = new Window("palette", L("processing"), undefined);
var progressBar = progressWindow.add("progressbar", undefined, 0, dataRows.length);
progressBar.preferredSize.width = 300;
progressWindow.show();
// é圢ïŒã¢ãŒãããŒã0ãšããã®äžã«ä¹ã£ãŠãããªããžã§ã¯ã
var templateArtboard = targetDoc.artboards[0];
var placementRect = templateArtboard.artboardRect;
targetDoc.artboards.setActiveArtboardIndex(0);
targetDoc.selectObjectsOnActiveArtboard();
var templateItems = targetDoc.selection;
if (!templateItems || templateItems.length === 0) {
progressWindow.close();
alert(L("noTemplate"));
return;
}
// é圢1ã»ã«ã®ãµã€ãºïŒã¢ãŒãããŒã0ã®ãµã€ãºïŒ
var cellWidth = placementRect[2] - placementRect[0];
var cellHeight = placementRect[1] - placementRect[3];
// ã°ãªããå
šäœã®å¹
ã»é«ããæ±ããã«ã³ãã¹ã®å€©å°ã»å·Šå³äžå€®ãžé
眮
var dataCount = dataRows.length;
var gridRows = Math.ceil(dataCount / columnCount);
var occupiedColumns = (columnCount < dataCount) ? columnCount : dataCount;
var gridWidth = occupiedColumns * cellWidth + (occupiedColumns - 1) * gap;
var gridHeight = gridRows * cellHeight + (gridRows - 1) * gap;
var canvasWidth = canvasBounds[2] - canvasBounds[0];
var canvasHeight = canvasBounds[1] - canvasBounds[3];
var leftMargin = Math.round((canvasWidth - gridWidth) / 2);
var topMargin = Math.round((canvasHeight - gridHeight) / 2);
var gridLeft = canvasBounds[0] + leftMargin;
var gridTop = canvasBounds[1] - topMargin;
var deltaX = gridLeft - placementRect[0];
var deltaY = gridTop - placementRect[1];
templateArtboard.artboardRect = [gridLeft, gridTop, gridLeft + cellWidth, gridTop - cellHeight];
for (var i = 0; i < templateItems.length; i++) {
templateItems[i].translate(deltaX, deltaY);
}
placementRect = templateArtboard.artboardRect; // ç§»ååŸã®äœçœ®ãã°ãªããé
眮ã®åºæºã«ãã
// éèŠïŒ2ä»¶ç®(i=1)ããå
ã«åŠçããïŒã¿ã°ãç¶æããããïŒ
for (var i = 1; i < dataRows.length; i++) {
progressBar.value = i;
progressWindow.update();
var col = i % columnCount;
var row = Math.floor(i / columnCount);
var offsetX = (cellWidth + gap) * col;
var offsetY = -(cellHeight + gap) * row;
var newArtboard = targetDoc.artboards.add([
placementRect[0] + offsetX, placementRect[1] + offsetY,
placementRect[2] + offsetX, placementRect[3] + offsetY
]);
newArtboard.name = (dataRows[i][nameColumnIndex] || "Data_" + (i + 1)).toString();
// é圢ãªããžã§ã¯ããè€è£œãã察å¿ããã¢ãŒãããŒããžç§»åããŠæµã蟌ã¿
for (var j = 0; j < templateItems.length; j++) {
var duplicatedItem = templateItems[j].duplicate();
duplicatedItem.translate(offsetX, offsetY);
replaceTextRecursive(duplicatedItem, headers, dataRows[i]);
}
}
// æåŸã«1ä»¶ç®(i=0)ãæžãæãã
progressBar.value = dataRows.length;
progressWindow.update();
templateArtboard.name = (dataRows[0][nameColumnIndex] || "Data_1").toString();
for (var k = 0; k < templateItems.length; k++) {
replaceTextRecursive(templateItems[k], headers, dataRows[0]);
}
targetDoc.selection = null;
progressWindow.close();
app.redraw();
if (!isPreview) {
alert(L("done").replace("#count#", String(dataRows.length)));
}
}
/* ãå®è¡ãïŒããã¥ã¡ã³ããå¥åä¿åã§è€è£œããæµã蟌ãã§ãã€ã¢ãã°ãéãã / Run: duplicate via Save As, merge, then close the dialog */
runButton.onClick = function () {
if (dataRows.length === 0) return;
var layout = prepareLayout();
if (!layout) return;
var importDocument;
try {
importDocument = duplicateDocumentBySaveAs(doc);
} catch (e) {
alert(L("dupFailed").replace("#detail#", String(e)));
return;
}
mainDialog.close();
performImport(importDocument, layout, false);
};
/* æ¢ã«éããŠãããã¬ãã¥ãŒçšããã¥ã¡ã³ããæ¢ãïŒç¡ããã° nullïŒ/ Find the already-open preview document (null if none) */
function getOpenPreviewDocument() {
if (!previewFile) return null;
for (var i = 0; i < app.documents.length; i++) {
try {
if (app.documents[i].fullName.fsName === previewFile.fsName) return app.documents[i];
} catch (e) { }
}
return null;
}
/* ãã¬ãã¥ãŒçšããã¥ã¡ã³ããéãããã¬ãã¥ãŒçšãã¡ã€ã«ãåé€ / Close the preview document and remove the preview file */
function cleanupPreviewFile() {
var openedPreview = getOpenPreviewDocument();
if (openedPreview) {
try { openedPreview.close(SaveOptions.DONOTSAVECHANGES); } catch (e) { }
}
if (previewFile && previewFile.exists) {
try { previewFile.remove(); } catch (e) { }
}
previewFile = null;
}
/*
ãã¬ãã¥ãŒãçæã»æŽæ° / Build or refresh the preview.
æ¢åã®ãã¬ãã¥ãŒããã¥ã¡ã³ããããã°äžæŠéããå
ããã¥ã¡ã³ãããè€è£œãã¡ã€ã«ãäœãçŽããŠéãã
æµã蟌ã¿çµæã¯ä¿åããªããããæ¯åã¯ãªãŒã³ãªéåœ¢ç¶æ
ããå§ãŸãã
*/
function runPreview() {
if (dataRows.length === 0) return false;
var layout = prepareLayout();
if (!layout) return false;
// æ¢åã®ãã¬ãã¥ãŒããã¥ã¡ã³ããããã°éããïŒæµã蟌ã¿çµæã¯ç Žæ£ïŒ
var openedPreview = getOpenPreviewDocument();
if (openedPreview) {
try { openedPreview.close(SaveOptions.DONOTSAVECHANGES); } catch (e) { }
}
// å
ããã¥ã¡ã³ããããã¬ãã¥ãŒçšã®è€è£œãã¡ã€ã«ãæ¯åäœãçŽã
var previewDocument;
try {
var sourceFile = doc.fullName;
if (!previewFile) {
previewFile = buildDuplicateFilePath(sourceFile, "preview");
}
if (previewFile.exists) {
previewFile.remove();
}
if (!sourceFile.copy(previewFile)) throw new Error("File copy failed");
previewDocument = app.open(previewFile);
} catch (e) {
alert(L("dupFailed").replace("#detail#", String(e)));
previewFile = null;
return false;
}
performImport(previewDocument, layout, true);
return true;
}
/* ããã¬ãã¥ãŒãïŒãªã³ã§è¡šç€ºããªãã§ãã¬ãã¥ãŒçšããã¥ã¡ã³ããéãã / Preview checkbox: show on, close the preview document off */
previewCheckbox.onClick = function () {
if (!previewCheckbox.value) {
cleanupPreviewFile();
return;
}
if (!runPreview()) previewCheckbox.value = false;
};
/* ããã£ã³ã»ã«ãïŒãã¬ãã¥ãŒçšãã¡ã€ã«ãåé€ããŠéãã / Cancel: remove the preview file and close the dialog */
cancelButton.onClick = function () {
cleanupPreviewFile();
mainDialog.close();
};
/* ã¢ãŒãããŒãåã®åç
§é
ç®ã倿Žãããããã¬ãã¥ãŒäžã¯è€è£œãã¡ã€ã«ãéãçŽããŠæŽæ° / Refresh the preview when the artboard-name field changes */
artboardNameDropdown.onChange = function () {
if (previewCheckbox.value) runPreview();
};
// =========================================
// ããã¹ãã®çœ®æ / Text replacement
// =========================================
/* ãªããžã§ã¯ããååž°çã«èµ°æ»ããããã¹ãå
ã® <ã¿ã°> ãããŒã¿å€ãžçœ®æ / Walk objects recursively and replace <tag> placeholders in text with data values */
function replaceTextRecursive(pageItem, headerKeys, rowValues) {
if (!pageItem) return;
if (pageItem.typename === "TextFrame") {
var textContent = pageItem.contents;
if (textContent == null) return;
for (var k = 0; k < headerKeys.length; k++) {
var headerKey = trimAndStripBom(headerKeys[k]);
if (headerKey === "") continue;
var placeholderTag = "<" + headerKey + ">";
if (textContent.indexOf(placeholderTag) !== -1) {
var value = (rowValues && rowValues.length > k && rowValues[k] != null) ? String(rowValues[k]) : "";
// å
šåºçŸã眮æïŒExtendScriptå®å
šïŒ
textContent = textContent.split(placeholderTag).join(value);
}
}
pageItem.contents = textContent;
} else if (pageItem.typename === "GroupItem") {
for (var i = 0; i < pageItem.pageItems.length; i++) {
replaceTextRecursive(pageItem.pageItems[i], headerKeys, rowValues);
}
}
}
mainDialog.show();
})();