Question

I am trying to replicate some functionality from a Excel document with some macros in a Google Spreadsheet. The end goal is to export a fixed-width txt file. Unfortunately, the vendor cannot use a CSV file. So, does anybody know of a way to generate a fixed-width TXT file using Google Scripts?

Was it helpful?

Solution

Just in case anybody else comes looking. I used a few sources and came up with this:

function saveAsFixedWidthTxt() {
  // get Spreadsheet Name
  var fileName = SpreadsheetApp.getActiveSpreadsheet().getName();
  //var fileName = SpreadsheetApp.getActiveSheet().getSheetName();

  // get Directory the Spreadsheet is stored in.
  var dirName = DocsList.getFileById(SpreadsheetApp.getActive().getId()).getParents()[0].getName();

  // Add the ".txt" extension to the file name
  fileName = fileName + ".txt";

  // Convert the range data to fixed width format
  var txtFile = convertRangeToTxtFile_(fileName);

  // Delete existing file
  deleteDocByName(fileName);

  // Create a file in the Docs List with the given name and the data
  DocsList.getFolder(dirName).createFile(fileName, txtFile);
}

function convertRangeToTxtFile_(txtFileName) {
  try {
    var txtFile = undefined;
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getSheets()[0];
    var rows = sheet.getDataRange();
    var data = rows.getValues();

    // Loop through the data in the range and build a string with the data
    if (data.length > 1) {
      var txt = "";
      for (var row = 2; row < data.length; row++) {

        for (var j=6; j<=10; j++){

          if(data[row][j] != ''){

            // Employee ID
            var empID = "" + data[row][3];
            txt += empID;
            //Fill to 6 characters
            for (i=empID.length; i<6; i++){
              txt += " ";
            }

            // Name
            var fullName = data[row][5] + " " + data[row][4]
            txt += fullName;
            //Fill to 43 characters
            for (i=fullName.length; i<44; i++){
              txt += " ";
            }

            // etc, etc to build out your line

            txt += "\r\n";
          }
        }
      }
      txtFile = txt;
    }
    return txtFile;
  }
  catch(err) {
    Logger.log(err);
    Browser.msgBox(err);
  }
}

function deleteDocByName(fileName){
  var docs=DocsList.find(fileName)
  for(n=0;n<docs.length;++n){
    if(docs[n].getName() == fileName){
      var ID = docs[n].getId()
      DocsList.getFileById(ID).setTrashed(true)
    }
  }
}

OTHER TIPS

This will work:

  1. export the sheet as a xlsx, then open that file in Excel.
  2. Export that file as Space Delimited Text (.prn, for some reason).
  3. Change the file extension on the resultant file to .txt.

This will result in a file like this:

Column    Another   Column 3
Val 1            2  $    5.00

Or do you need to get a .txt file directly out of Google Apps Script?

Edit since a direct .txt download is necessary.

Here's how you could design a script to do that:

  1. Find a way to convert sheet.getColumnWidth(n) to a number of spaces. You may find that there are 5 pixels to 1 character, or whatever the ratio
  2. Run getColumnWidth() for each column to find the width you need for each column. Alternatively, find the length longest string in each cell.
  3. Go through each cell and add it to a large string you begin building. As you add it, add the number of spaces necessary to match the value converted from getColumnWidth(). At the end of each row, append \n to represent a new line.

Once the output string is complete, you could then use the Content Service to download the text like so:

ContentService.createTextOutput(youBigString).downloadAsFile('filename.txt')

This would involve deploying your script as a web app, which could work well - you'd go to a URL and the page would trigger a download of the fixed-width file.

In my case, DocList use returns ReferenceError.@MSCF your lines 7 & 27 :

var dirName = DocsList.getFileById(SpreadsheetApp.getActive().getId()).getParents()[0].getName();

DocsList.getFolder(dirName).createFile(fileName, txtFile);

become

var dirName = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getParents().next().getId();

DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getParents().next().createFile(fileName, txtFile);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top