-
-
Save schlos/0d4501981aab2d9f08553c08e3a4fdee to your computer and use it in GitHub Desktop.
Spreadsheet Splitter - Google Apps Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Creates new spreadsheets based on a column containing email addresses | |
// in the starting spreadsheet. | |
// Each new spreadsheet will contain the full set of rows for that email address. | |
// It will then be shared with that email address and a link emailed. | |
var EMAIL_COLUMN = 2; //Use the number: A=1,B=2,Z=26 etc | |
var ALSO_SHARE_WITH = ""; // Add any additional addresses here. Separated multiples with commas. | |
var NUM_HEADER_ROWS = 1; // The number of header rows. | |
// Do not change anything below this line | |
// 24 Nov 2010 - test mode works correctly after Google changes (session broke after Browser.msgBox) | |
var FLAG_COLUMN_HEADER_NAME = "Processed to spreadsheet"; | |
var TEST = true; | |
var activeUserEmail = Session.getActiveUser().getEmail(); | |
function doSegmentation() { | |
try{ | |
// Get the currently selected sheet | |
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); | |
// Test mode | |
var answer = Browser.msgBox("Run in test mode?", | |
"This will process the current sheet \"" + sheet.getName() + | |
"\". If you run in test mode, the full process is run as normal but any spreadsheets "+ | |
"that are created are not shared and email is only ever sent to you " + | |
"and no one else. Do you want to run in test mode?", | |
Browser.Buttons.YES_NO_CANCEL); | |
switch (answer) { | |
case "yes": | |
TEST = true; | |
break; | |
case "no": | |
TEST = false;; | |
break; | |
case "cancel": | |
sheet.getParent().toast("Processing cancelled."); | |
return; | |
} | |
// Get index of flag column - create if necessary | |
var flagColumnIndex = getFlagColumnIndex_(sheet,FLAG_COLUMN_HEADER_NAME); | |
//Browser.msgBox(flagColumnIndex); | |
//Logger.log(flagColumnIndex); | |
// Get the full range of data to process | |
var range = sheet.getDataRange(); | |
var values = range.getValues(); | |
// get the first key to process | |
var key = getNextUnprocessedKey_(values, EMAIL_COLUMN-1, flagColumnIndex); | |
// get each key and process the rows containing that key | |
while (key) { | |
var rowIndexes = []; | |
rowIndexes = getUnprocessedByKey_(values, EMAIL_COLUMN-1, key, flagColumnIndex); | |
var message = "Processing " + key + ". " + rowIndexes.length + " rows to process."; | |
sheet.getParent().toast(message, "Progress"); | |
//Browser.msgBox(rowIndexes.toString()); | |
process_(sheet, values, key, rowIndexes, flagColumnIndex); | |
var values = range.getValues(); //reset values after processing (flags loaded) | |
key = getNextUnprocessedKey_(values, EMAIL_COLUMN-1, flagColumnIndex); | |
} | |
sheet.getParent().toast("Processing completed successfully.", "Progress", -1); | |
} catch(error){ | |
//sheet.getParent().toast("Error: " + error, -1); | |
Browser.msgBox("Error: " + error); | |
//logToSheet_("Error (doEmailToBeDeletedUsers): " + error); | |
} | |
} | |
function process_(sheet, values, key, rowIndexes, flagColumnIndex) { | |
// rowIndexes is required so we can "stamp" the rows as processed | |
//create spreadsheet | |
var ssNew = SpreadsheetApp.create(sheet.getParent().getName()+" for " + key); | |
var collabs = ALSO_SHARE_WITH ? key + ", "+ ALSO_SHARE_WITH : key; | |
// bug (logged) with emailing collabs so we do it manually later in this function | |
// http://code.google.com/p/google-apps-script-issues/issues/detail?id=170 | |
if (!TEST) { | |
ssNew.addCollaborators(collabs, {editorAccess:true, emailInvitations:false}); | |
} | |
var sheetNew = ssNew.getSheets()[0]; | |
// Set header rows | |
var headerValues = sheet.getRange(1,1,NUM_HEADER_ROWS, sheet.getLastColumn()-1).getValues(); | |
sheetNew.getRange(1,1,NUM_HEADER_ROWS, sheet.getLastColumn()-1).setValues(headerValues); | |
// get rows to copy | |
var rowsToCopy = []; | |
for(var i = 0; i < rowIndexes.length ; i++) { | |
rowsToCopy.push(values[rowIndexes[i]]); | |
} | |
// add rows to sheet | |
sheetNew.getRange(NUM_HEADER_ROWS+1,1,rowsToCopy.length,rowsToCopy[0].length).setValues(rowsToCopy); | |
// tweak example - set the fifth column to 500pixels wide | |
//sheetNew.setColumnWidth(4, 500) | |
//send ss link email | |
var testmsg = TEST ? "This is a test that would have been sent to " + collabs + "." : ""; | |
var html = "Here is a link to <a href=\"" + ssNew.getUrl() + "\">" + | |
ssNew.getName() + "</a><br><br>"; | |
var body = "Here is a link to "+ssNew.getUrl()+": "+ssNew.getName()+"\n\n"; | |
var recipients = TEST ? activeUserEmail : collabs; | |
//Browser.msgBox("recipients:"+recipients+ "."); //debug | |
MailApp.sendEmail(recipients, ssNew.getName(), | |
testmsg + "\n\n" + body, {htmlBody: testmsg + "<br><br>" + html}); | |
// mark each row as processed | |
for(var i = 0; i < rowIndexes.length ; i++) { | |
sheet.getRange(rowIndexes[i]+1, flagColumnIndex+1).setValue(ssNew.getUrl()); | |
} | |
} | |
function getFlagColumnIndex_(sheet, headerName) { | |
// Looks for the specified column header name in the first row of the sheet | |
// and returns the column index (0 based index). | |
// Creates column if required (appends to end). Returns -1 if not found. | |
var row = 1; // look in the first row only | |
var headerColumnIndex = -1; | |
var value = ""; | |
for (var i = 0; i < sheet.getLastColumn(); ++i) { | |
value = sheet.getRange(row, i+1).getValue(); | |
if (value === headerName) { | |
var headerColumnIndex = i; | |
} | |
} | |
// if no column found, create one | |
if (headerColumnIndex === -1) { | |
sheet.insertColumnsAfter(sheet.getLastColumn(), 1); | |
var headerColumnIndex = sheet.getLastColumn(); | |
sheet.getRange(1,headerColumnIndex+1).setValue(headerName); | |
} | |
return headerColumnIndex; | |
} | |
function getNextUnprocessedKey_(values, keyColumnIndex, flagColumnIndex) { | |
// Returns the value of the key column where the data in flagColumnIndex is blank | |
// Process each row (not header so start at 1) | |
var key = ""; | |
for(var i = NUM_HEADER_ROWS; i < values.length ; i++) { | |
var value = values[i][flagColumnIndex]; | |
if (value === "") { | |
return values[i][keyColumnIndex]; | |
} | |
} | |
} | |
function getUnprocessedByKey_(values, keyColumnIndex, key, flagColumnIndex) { | |
// Returns an array containing row indexes (0 based) of rows | |
// where the row key matches and the flagColumnIndex is blank | |
// Process each row (not header so start at 1) | |
var rows = []; | |
for(var i = NUM_HEADER_ROWS; i < values.length ; i++) { | |
var keyVal = values[i][keyColumnIndex]; | |
var flagVal = values[i][flagColumnIndex]; | |
if ((flagVal === "") && (keyVal === key)) { | |
rows.push(i); | |
} | |
} | |
return rows; | |
} | |
function onOpen() { | |
var ss = SpreadsheetApp.getActiveSpreadsheet(); | |
var menuEntries = [ {name: "Create split sheets...", functionName: "doSegmentation"} ]; | |
ss.addMenu("Spreadsheet Splitter", menuEntries); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment