Skip to main content
Known Participant
February 27, 2015
Answered

Create Excel file using Indesign javascript

  • February 27, 2015
  • 5 replies
  • 3580 views

Hi All,

We can create csv file using indesign javascript. Is there any way to create excel file using indesign javascript?

Thanks in Advance

This topic has been closed for replies.
Correct answer Trevor:

Hi all,

This is a way of generating an excel file from an InDesign table using a combination of jsx, vbs and applescript.

Quite a long discussion on it Open With below is a better implementation of the suggestions there.

// Exports SIMPLE tables to proper excel file single and double quotes in the table would have to be escaped on the Mac version

// Does not take Unicode file names

// with a bit of brain racking can be developed to deal with merged cells and nested tables

// Pieced together by Trevor (wwww.creative-scripts.com coming soonish) based on the referenced sources

// Sold AS IS https://forums.adobe.com/thread/1718021

var doc = app.properties.activeDocument && app.activeDocument,

       myTable = myTable || getTable (doc);

if (!myTable) {alert ("Take a break, needs a document with a table in it!"); exit();};

var filePath = new File (Folder.temp + "/" + +new Date + ".xlsx"),

    osFilePath = filePath.fsName;

if ($.os[0] === "M")  osFilePath =  osFilePath.replace(/(.)(\/)/g,"$1:").replace(/\//, "");

exportTable (myTable, osFilePath);

if (confirm ("Open new excel file")) filePath.execute(false);

exit()

function exportTable (myTable, filePath)

    {

        var  numberOfRows = myTable.rows.length,

               rowNumber, columnNumber,

               isMac = $.os[0] === "M",

               rowContents = [],

               setRange, openMark, closeMark;

        if (isMac)

            {

                setRange = 'set value of range "A';

                openMark = '" to {';

                closeMark = '}';

            }

        else

            {

                setRange = 'app.Range("A';

                openMark = '") = Array(';

                closeMark = ')';

            }

for (var z = 0, rowNumber = 0; rowNumber < numberOfRows; rowNumber++) {

    var  numberOfColumns = myTable.rows[rowNumber].columns.length,

            toRange = GetExcelColumnName (numberOfColumns - 1),

            columnContents = [];

     for (columnNumber = 0; columnNumber < numberOfColumns; columnNumber++) {

         var cellContents = myTable.rows[rowNumber].cells.everyItem().contents;

         columnContents  = '"' + cellContents.join('", "') + '"';

     }

    rowContents[rowNumber] = setRange + ++z  + ":"  + toRange+ z + openMark  + columnContents + closeMark;

}

var tableData = rowContents.join("\n") + "\n";

               if (isMac)

                    {

                        // Thanks Hans https://forums.adobe.com/message/5607799#5607799

                       var myAppleScript =

                        '''set excelRunning to isRunning("Microsoft Excel")

                           tell application "Microsoft Excel"

                           set theWorkbook to make new workbook

                           tell sheet (1) of theWorkbook'''

                           + tableData + '''

                           end tell

                           save workbook as theWorkbook filename "''' + filePath + '''"

                           close active workbook

                           if not excelRunning then tell application "Microsoft Excel" to quit

                           end tell

                           on isRunning(appName)

                                tell application "System Events" to (name of processes) contains appName

                           end isRunning

                        ''';

                      app.doScript (myAppleScript, ScriptLanguage.APPLESCRIPT_LANGUAGE);

                    }

                else

                    {

                        // Thanks Calos https://forums.adobe.com/message/5607799#5607799

                        // changed by me :-)

                         var vbscript =

                         '''Dim app

                            Set app = CreateObject("Excel.Application")

                            'take away the ' from the line below if you want to see excel do it's stuff

                            'app.visible = true

                            Dim newDoc, sheet

                            Set newDoc = app.Workbooks.Add()

                            Set sheet = newDoc.Worksheets(1)

                            '''

                            + tableData

                            + 'newDoc.SaveAs "' + filePath + '''"

                            app.Quit

                            Set newDoc = nothing

                            Set app = nothing

                          ''';

                        app.doScript (vbscript, ScriptLanguage.VISUAL_BASIC);

                    }

            }

function GetExcelColumnName (columnNumber) {// 0 is A 25 is Z 26 is AA etc.

    // parsed from http://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa

     var dividend = columnNumber + 1,

            columnName = "",

            modulo;

    while (dividend > 0)  {

        modulo = (dividend - 1) % 26;

        columnName = String.fromCharCode (65 + modulo) + columnName;

        dividend = Math.floor((dividend - modulo) / 26);

    }

    return columnName;

}

function getTable (doc) { // thanks Marc http://forums.adobe.com/message/6087322#6087322

    if (!doc) return false;

    app.findTextPreferences = null;

    app.findTextPreferences.findWhat = "\x16";

    var tables = doc.findText();

    if (tables.length) return tables[0].parentStory.tables[0];

    return false;

};

5 replies

Inspiring
March 2, 2015

Yes, but quite difficult and time consuming.

If you are looking at the latest Excel file format (xlsx), it is a zipped file with bunch of XML files inside. You can use your JavaScript to produce XML files and command line script to zip them. If it helps, you can use xslt on the way.

Older Excel xls format is just one uncompressed xml file, which is much easier to produce.

The biggest advantage of this approach is that you can add formatting to ecxel, custom groups, formulas and multiple work sheets.

On a mac all tools are available from OS, on PC you will might need to add some command line utilities, depends on your Windows version.

By all means, it is good fun to do but not a five minutes job. If I did it for a client I would quote a week. I would advise to look at simpler workarounds suggested before - scv export, applescript, etc..

Trevor:
Trevor:Correct answer
Legend
March 2, 2015

Hi all,

This is a way of generating an excel file from an InDesign table using a combination of jsx, vbs and applescript.

Quite a long discussion on it Open With below is a better implementation of the suggestions there.

// Exports SIMPLE tables to proper excel file single and double quotes in the table would have to be escaped on the Mac version

// Does not take Unicode file names

// with a bit of brain racking can be developed to deal with merged cells and nested tables

// Pieced together by Trevor (wwww.creative-scripts.com coming soonish) based on the referenced sources

// Sold AS IS https://forums.adobe.com/thread/1718021

var doc = app.properties.activeDocument && app.activeDocument,

       myTable = myTable || getTable (doc);

if (!myTable) {alert ("Take a break, needs a document with a table in it!"); exit();};

var filePath = new File (Folder.temp + "/" + +new Date + ".xlsx"),

    osFilePath = filePath.fsName;

if ($.os[0] === "M")  osFilePath =  osFilePath.replace(/(.)(\/)/g,"$1:").replace(/\//, "");

exportTable (myTable, osFilePath);

if (confirm ("Open new excel file")) filePath.execute(false);

exit()

function exportTable (myTable, filePath)

    {

        var  numberOfRows = myTable.rows.length,

               rowNumber, columnNumber,

               isMac = $.os[0] === "M",

               rowContents = [],

               setRange, openMark, closeMark;

        if (isMac)

            {

                setRange = 'set value of range "A';

                openMark = '" to {';

                closeMark = '}';

            }

        else

            {

                setRange = 'app.Range("A';

                openMark = '") = Array(';

                closeMark = ')';

            }

for (var z = 0, rowNumber = 0; rowNumber < numberOfRows; rowNumber++) {

    var  numberOfColumns = myTable.rows[rowNumber].columns.length,

            toRange = GetExcelColumnName (numberOfColumns - 1),

            columnContents = [];

     for (columnNumber = 0; columnNumber < numberOfColumns; columnNumber++) {

         var cellContents = myTable.rows[rowNumber].cells.everyItem().contents;

         columnContents  = '"' + cellContents.join('", "') + '"';

     }

    rowContents[rowNumber] = setRange + ++z  + ":"  + toRange+ z + openMark  + columnContents + closeMark;

}

var tableData = rowContents.join("\n") + "\n";

               if (isMac)

                    {

                        // Thanks Hans https://forums.adobe.com/message/5607799#5607799

                       var myAppleScript =

                        '''set excelRunning to isRunning("Microsoft Excel")

                           tell application "Microsoft Excel"

                           set theWorkbook to make new workbook

                           tell sheet (1) of theWorkbook'''

                           + tableData + '''

                           end tell

                           save workbook as theWorkbook filename "''' + filePath + '''"

                           close active workbook

                           if not excelRunning then tell application "Microsoft Excel" to quit

                           end tell

                           on isRunning(appName)

                                tell application "System Events" to (name of processes) contains appName

                           end isRunning

                        ''';

                      app.doScript (myAppleScript, ScriptLanguage.APPLESCRIPT_LANGUAGE);

                    }

                else

                    {

                        // Thanks Calos https://forums.adobe.com/message/5607799#5607799

                        // changed by me :-)

                         var vbscript =

                         '''Dim app

                            Set app = CreateObject("Excel.Application")

                            'take away the ' from the line below if you want to see excel do it's stuff

                            'app.visible = true

                            Dim newDoc, sheet

                            Set newDoc = app.Workbooks.Add()

                            Set sheet = newDoc.Worksheets(1)

                            '''

                            + tableData

                            + 'newDoc.SaveAs "' + filePath + '''"

                            app.Quit

                            Set newDoc = nothing

                            Set app = nothing

                          ''';

                        app.doScript (vbscript, ScriptLanguage.VISUAL_BASIC);

                    }

            }

function GetExcelColumnName (columnNumber) {// 0 is A 25 is Z 26 is AA etc.

    // parsed from http://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa

     var dividend = columnNumber + 1,

            columnName = "",

            modulo;

    while (dividend > 0)  {

        modulo = (dividend - 1) % 26;

        columnName = String.fromCharCode (65 + modulo) + columnName;

        dividend = Math.floor((dividend - modulo) / 26);

    }

    return columnName;

}

function getTable (doc) { // thanks Marc http://forums.adobe.com/message/6087322#6087322

    if (!doc) return false;

    app.findTextPreferences = null;

    app.findTextPreferences.findWhat = "\x16";

    var tables = doc.findText();

    if (tables.length) return tables[0].parentStory.tables[0];

    return false;

};

Known Participant
March 6, 2015

Thanks to everyone. Hi "Trevor" thank you very much for the solution.

Colin Flashman
Community Expert
Community Expert
March 1, 2015

There is a year-old post that may do something similar to what the OP wants: Exporting data in tables to an Excel spreadsheet?

If the answer wasn't in my post, perhaps it might be on my blog at colecandoo!
Peter Kahrel
Community Expert
Community Expert
February 27, 2015

In short, the answer is 'No, you can't create an Excel file using JavaScript.' You might, if you know Excel's file format, but that would be a nonsensical exercise. Do as pixxxel schubser said: create a tab-separated text file because that can be opened in Excel.

Peter

Loic.Aigon
Legend
February 27, 2015

Hi all,

CSV files should be openable too. It's just that Excel uses semi-colons as separator for what I can remember.  Pretty certain I opened csv files with excel. That's why I second Peter on the non sense here.

Loic

pixxxelschubser
Community Expert
Community Expert
March 1, 2015

Loic.Aigon schrieb:

Hi all,

CSV files should be openable too. It's just that Excel uses semi-colons as separator for what I can remember.  Pretty certain I opened csv files with excel. That's why I second Peter on the non sense here.

Loic

Loic.Aigon‌,

yes and no.

Yes, because of: you can create CSV or tab separated TXT by using Javascript.

Yes, because of: you can copy the contents with Javascript and open MS Excel im combination with VBS or Applescript in Javascript and save the file as XLS

No, because of: this was not the question.

Senthilvel S schrieb:

… Is there any way to create excel file using indesign javascript?

Thanks in Advance

And the short answer is (like pkahrel‌ said before): No, there is no way with Javascript (alone).

pixxxelschubser
Community Expert
Community Expert
February 27, 2015

Try as workaround:

create a tab separated*txt. This file can be opened in MS Excel.

Jump_Over
Legend
February 27, 2015

Hi,

If found - beware Microsoft!

Jarek