Looking for a way to export Object/Shape or Artboard size data to a CSV or similar File

Community Beginner ,
Dec 15, 2021 Dec 15, 2021

Copy link to clipboard

Copied

As in the title : I am looking for a way to select multiple objects or artboards, and export that information to a CSV File.  Would figuring out a script be the correct path? (any help here would be grateful as I am just dipping my toes into the world of scripting, and very much a novice). 

 

The intent here, is to import that data into InDesign and create multiple pages similar to artboards, but from the data in AI into ID to create individual layouts / pages based on AI data/sizes.

 

Maybe there is an easier way I am just not aware of?

Thanks all!

TOPICS
Draw and design , How to , Import and export , Scripting , Tools

Views

171

Likes

Translate

Translate

Report

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 2 Correct answers

Adobe Community Professional , Jan 04, 2022 Jan 04, 2022
Hey brother. No apologies necessary. Everybody's gotta learn at some point, and I learned what I know from the brilliant folks around here who helped me along in my journey. The code you have there appears to work just fine for building the appropriate 2D array for the csv data. great job. So it looks like your sticking point was getting that data into an output file. You can delete that whole pseudo-code section and replace it with this: var outFile = File("~/Desktop/super_awesome_csv_data....

Likes

Translate

Translate
Adobe Community Professional , Jan 05, 2022 Jan 05, 2022
ugh. i'm so dumb. i just had a whole message written out with tons of questions about your setup and what you were doing before, during and after the script and what things you might have seen while it was happening etc... .. And then i realized.. The function call to writeCsvData() is missing the second argument which represents the path to the CSV. Change line 45 (of the script in the github link above) to this:  writeCsvData(rows,csvFilePath); The script wasn't sending a path to the wri...

Likes

Translate

Translate
Adobe Community Professional ,
Dec 15, 2021 Dec 15, 2021

Copy link to clipboard

Copied

i'm not sure of any way to do this without a script.

 

some pseudo-code:

 

//generate the csv data

var docInfo = [["name","width","height","fill color"]]; //2d array

for each artboard/selected object in the document

    curInfo = ["item1","150","200","blue"]; //array of info for this object

    docInfo.push(curInfo)

 

//format the output string

var outputString = "";

for each element of docInfo

    outputString += docInfo[index] + "\n";

 

//write the csv data to the file

var file = File("path/to/file/data.csv");

file.open("w");

for each element of docInfo array

    file.write(

file.close();

Likes

Translate

Translate

Report

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 Beginner ,
Jan 02, 2022 Jan 02, 2022

Copy link to clipboard

Copied

Thank you DilliamWowling -

 

Apologies I am fairly new to writing scripts and can follow what you've laid out, but am having trouble implmenting, if you'd be able to elaborate more?  I've been able to hobble together getting the data I need outputted, but not sure how to pass through the information (apologies if this seems rudementary in execution).  

 

The code I have so far laid out that alerts for all selected objects :

 

// Alert to current selected Object

document = app.activeDocument;
layer = document.layers.getByName('Layer 1');
var selections = app.activeDocument.selection;

// HANDLING HEADER ROW FOR CSV OUTPUT
var rows = [];
rows.push(["NAME","WIDTH","HEIGHT","LOCATION"]);
for (var i=0; i<selections.length; i+=1){
    rows.push(getItemWidthHeight(selections[i]));
}
alert(getCSVtext(rows));

function getCSVtext(rows) {
    var text = "";
    for (var i = 0; i < rows.length; i+=1) {
        var row = rows[i];
        text += row[0];
        text += ",";
        text += row[1];
        text += ",";
        text += row[2];
        text += ",";
        text += row[3];
        text += "\r\n";
    }
    return text;
}

function getItemWidthHeight(item) {
    var itemWtoIn   = item.width * .01389;    
// Convert W from Points > Inches

    var itemWrnd    = (Math.ceil((itemWtoIn.toFixed(3)) * 8) / 8);      
// Round W up to nearest 1/8" for Arch. Measurement

    var itemHtoIn   = item.height * .01389;  
// Convert W from Points > Inches

    var itemHrnd    = (Math.ceil((itemHtoIn.toFixed(3)) * 8) / 8);      
// Round H up to nearest 1/8" for Arch. Measurement

    var row         = [item.name, itemWrnd, itemHrnd];
    return row;
}

// ------ SUDOCODE FOR OUTPUT TO CSV -------

//generate the csv data
var docInfo = [["NAME","WIDTH","HEIGHT"]]; 

//2d array for each artboard/selected object in the document
    curInfo = [text];  // PULLING INFO FROM ABOVE

    //array of info for this object
    docInfo.push(curInfo)

//format the output string
var outputString = "";
for each element of docInfo
    outputString += docInfo[index] + "\n";

//write the csv data to the file
var file = File("data.csv");
file.open("w");
for each element of docInfo array
    file.write(
file.close();

 

I'm learning - so thank you for bearing with me. 

 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 04, 2022 Jan 04, 2022

Copy link to clipboard

Copied

Hey brother. No apologies necessary. Everybody's gotta learn at some point, and I learned what I know from the brilliant folks around here who helped me along in my journey.

 

The code you have there appears to work just fine for building the appropriate 2D array for the csv data. great job. So it looks like your sticking point was getting that data into an output file. You can delete that whole pseudo-code section and replace it with this:

 

var outFile = File("~/Desktop/super_awesome_csv_data.csv");
outFile.open("w");
outFile.write(rows.join("\n"));
outFile.close();

 

That's all you need to write your data to a local file (or you could just as easily write to a network volume or mounted external drive, etc.  You can use relative file paths as well if you prefer, but I've had better long term results with absolute paths.

 

Notice the second to last line that uses the .write() method. I'm passing in the result of rows.join("\n"); The join method does essentially what your getCSVtext() function does. It takes the array "rows" and returns a new string by concatenating all of the elements and separating them by the given character, eg "\n". Since we have a 2D array, that means that this join() function will return several arrays, separated by a new line character. So that's almost what we want, right...? But what about a comma separated string of those values??? Default javascript behavior to the rescue! When you print an array (or use the .join() method) there's an implicit call to the Array.toString() function for which the default output is a string with comma separated values from the array. For example: 

 

var fruits = ["banana","apple","orange"];
$.writeln(fruits); // output: "banana, apple, orange"

So that's perfect. Because when we join the elements of the rows array, it automatically converts each subarray to a comma separated string which is exactly what we want for our csv data. You can use this same logic in your alert as well. 

 

Anywho, that's how you can get your own code working. However, there are a few other issues going on in your code that should be addressed. You have some global variable definitions which should be avoided at all costs. An example of this is where you define the variable "layer". if you don't explicitly use "var" when declaring the variable, and that variable doesn't already exist in the appropriate scope, then the variable will be created in the global scope where it can cause issues.

 

The second issue is that you've overwritten the default "document" variable. When you create a variable for the active document, use "doc" or "docRef" instead so you don't interfere with preexisting default variables.

 

And third, apropos of the aforementioned scope issues, it's always a good idea to wrap your entire script in some kind of container function. This helps ensure that all of the variables you create will remain within the scope of your current script and won't effect the performance or behavior of any other script. 

 

Lastly, and this isn't a critique as much as it is simply advice. There's an old addage in programming.. DRY. Don't repeat yourself. The beauty of coding is that you can write something once and then use it a million times if you want. So any time you find yourself writing the same thing more than a couple of times, it's probably a candidate for abstraction.

 

An example of this is converting points to inches. The process of converting points to inches never changes, so it's a perfect candidate for a function. Likewise, rounding to the nearest 8th inch. The logic never changes. so it's easier to write code if you can call a simple function and pass the number in. Then your code won't be cluttered with repetitious code like 

 

var itemWtoIn   = item.width * .01389;    
// Convert W from Points > Inches

    var itemWrnd    = (Math.ceil((itemWtoIn.toFixed(3)) * 8) / 8);      
// Round W up to nearest 1/8" for Arch. Measurement

    var itemHtoIn   = item.height * .01389;  
// Convert W from Points > Inches

    var itemHrnd    = (Math.ceil((itemHtoIn.toFixed(3)) * 8) / 8);      
// Round H up to nearest 1/8" for Arch. Measurement

 

But instead, it could look like this:

function ptToInch(pt)
{
    //convert points to inches
    return pt * .01389;
}

function roundTo8th(num)
{
    //round the given number to the nearest 1/8"
    return Math.ceil((num.toFixed(3)) * 8) / 8;
}

function getItemWidthHeight(item)
{
    var width = roundTo8th(ptToInch(item.width));
    var height = roundTo8th(ptToInch(item.height));
    return [item.name, width, height];
}

 

I've taken the liberty of rewriting the whole script utilizing the above advice. I've modularized everything so that it's easily reusable and easier to read and update. You can find it here:

https://github.com/wdjsdev/public_illustrator_scripts/blob/master/export_doc_data.js

 

Let me know if this was helpful or if it was a rambling wall of nonsense. Happy to answer any follow up questions.

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 04, 2022 Jan 04, 2022

Copy link to clipboard

Copied

Having just re-read the whole thread from the beginning, i want to apologize for including some bad habits in my pseudo code. i realize now that some of my critiques were actually about my bad idea and not your implementation.

 

Sorry about that. 😜

Likes

Translate

Translate

Report

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 Beginner ,
Jan 04, 2022 Jan 04, 2022

Copy link to clipboard

Copied

No worries! 😊

 

Thank you greatly!

 

I just ran the code, while it spits out the same alert (awesome!) It doesn't seem to output the CSV (Or I can't locate it - it's not on my desktop, doesn't show up in 'recent files' if putting somewhere else.  Any indication of where it might be going if it's being created?

 

 

Likes

Translate

Translate

Report

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 Beginner ,
Jan 04, 2022 Jan 04, 2022

Copy link to clipboard

Copied

Also! Thank you very, very kindly for the thorough explinations above!

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 05, 2022 Jan 05, 2022

Copy link to clipboard

Copied

ugh. i'm so dumb. i just had a whole message written out with tons of questions about your setup and what you were doing before, during and after the script and what things you might have seen while it was happening etc... ..

 

 

And then i realized.. The function call to writeCsvData() is missing the second argument which represents the path to the CSV. Change line 45 (of the script in the github link above) to this: 

writeCsvData(rows,csvFilePath);

 

The script wasn't sending a path to the write data function which obviously means it cannot write a file because it has no path. silly me.

Likes

Translate

Translate

Report

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 Beginner ,
Jan 05, 2022 Jan 05, 2022

Copy link to clipboard

Copied

BAM! Look at that! Like a charm!!! 😁🙌👏

 

I had to look for a sec - realized you must have meant line 145 (sent a pull req. to the GitPage).

 

Only question : will the absolute path listed work PC vs Mac or will that need to change?

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jan 05, 2022 Jan 05, 2022

Copy link to clipboard

Copied

LATEST

The only thing regarding your file path that might change with operating system  is how you reference network drives. The formatting  of the paths is the same either way, but on mac your network path will start with something like "/Volumes/NameOfDrive/Path/To/Folder" whereas on windows it will be something like "N:/Path/To/Folder".

 

Other than that, you can just use forward slashes in your file paths and it'll work fine on either OS. 

Likes

Translate

Translate

Report

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