Google Apps脚本可根据其他工作表的数据生成和填充工作表

时间:2017-03-31 19:38:05

标签: google-apps-script google-sheets

我维护一个跟踪蛋糕订单的电子表格工作簿。跟踪表(名为CakeOrders)上的列标题(A-H)如下:

(A1)取件日期,(B1)客户名称,(C1)电话号码,(D1)蛋糕上的文字,(E1)蛋糕味道,(F1)结霜味道,(G1)水果馅,(H1 )链接到PO

这些标题下方的每一行数据都对应一个新的采购订单(PO),其中包含唯一的日期,客户名称等。View CakeOrders sheet here.

在同一工作簿中的第二个工作表(名为Admin)上,我有一个运行匹配函数的表,以查找CakeOrders上每个列标题的Column#。这是设置的,这样我的脚本(调用这些列#s)将保持准确,即使我最终重新排列或添加Columns和新标题到CakeOrders表 - 由于匹配函数,脚本将始终引用相应的列在管理表上。 View the Admin sheet here.

我目前有一个脚本设置,允许我直接从此电子表格生成新的格式化电子表格(设计为空白PO)。该脚本根据所选行中的数据命名新工作表(或PO),并在列H中添加指向新PO的链接。

我想扩展此脚本,以便根据其原始行中的信息填充新PO上的选定单元格。

有没有人知道一个脚本,它允许我使用来自另一个特定行的数据填充新电子表格的特定单元格?

谢谢!

下面是我当前的脚本,它创建一个新的电子表格,其名称基于行内容,将新工作表存储在特定文件夹中,并包含指向原始行中电子表格的链接。

function onOpen() { 
  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  var customMenu = [{name: "Create PO", functionName: "Create"}]; 
   ss.addMenu("Create PO", customMenu); 
};

function Create() {
  var sheet = SpreadsheetApp.getActive().getSheetByName("Admin"); 
  var folderID = sheet.getRange("B2").getValue(); //These are column numbers
  var templateID = sheet.getRange("B3").getValue(); 
  var pickupDate = sheet.getRange("B4").getValue(); 
  var clientName = sheet.getRange("B5").getValue();
  var textOnCake = sheet.getRange("B6").getValue(); 
  var cakeFlavor = sheet.getRange("B7").getValue(); 
  var frostingFlavor = sheet.getRange("B8").getValue(); 
  var fruitFilling = sheet.getRange("B9").getValue(); 
  var POColumn = sheet.getRange("B10").getValue(); 

  var ss = SpreadsheetApp.getActiveSheet(); // Back to CakeOrders sheet
  var cell = ss.getActiveCell(); 
  var row = cell.getRow(); //User has to pick the correct row

  if (row <= 1){ 
   Browser.msgBox("Cannot create new document within the header. Please select the row to which you'd like to add a new PO doc and run the script again.");
    return; 
  }

  try{

  var pickupDateValue = Utilities.formatDate(ss.getRange(row,pickupDate).getValue(), "America/Chicago", "MMddYY"); 
  } 
  catch(e) { 
  var pickupDateValue = ss.getRange(row,pickupDate).getValue();    
  }

  var clientNameValue = ss.getRange(row,clientName).getValue();//getting the actual values now using column numbers from admin sheet
  var textOnCakeValue = ss.getRange(row,textOnCake).getValue(); 
  var cakeFlavorValue = ss.getRange(row,cakeFlavor).getValue(); 
  var frostingFlavorValue = ss.getRange(row,frostingFlavor).getValue(); 
  var fruitFillingValue = ss.getRange(row,fruitFilling).getValue(); 
  var POColumnValue = ss.getRange(row,POColumn).getValue(); 

    if (POColumnValue != ""){ 
   Browser.msgBox("There is already content in the PO column. Please clear the contents and try again.");
    return; 
  }


  if (clientNameValue == "" || textOnCakeValue == "" || cakeFlavor == "" || frostingFlavor == ""|| fruitFilling == ""){ 
   Browser.msgBox("Client Name, Text On Cake, Cake Flavor, Frosting Flavor, and Fruit Filling are required. Please enter a value in each of these columns and then try again.");
    return; 
  }

  var docName = "PO." + pickupDateValue + "." + clientNameValue;   

  var template = DriveApp.getFileById(templateID);  
  var destFolder = DriveApp.getFolderById(folderID); 

  var newDocID = template.makeCopy(docName, destFolder).getId(); 
  var docLink = "https://docs.google.com/spreadsheets/d/" + newDocID; 
  ss.getRange(row,POColumn).setValue(docLink);
}

2 个答案:

答案 0 :(得分:0)

首先让我说,我并不是说这是唯一的,甚至是最好的方法。这就是我这样做的方式。我一生中大部分时间都是单独的程序员,所以我几乎总是这样做。

我可能会修改列标题,使它们成为单个字Camel Code,并将它们用作关联数组的键。因此,当我从一行中获取数据时,我会从表中构建一个如下所示的数组:

PickupDate  ClientName    Phone         CakeText             CakeFlavor     FrostingFlavor  FruitFilling    LinktoPO
4/15/2017   Bart Simpson  123-456-7899  Your Wierd Bart      Dessert Cactus Frozen Spinach  Tomato  
4/16/2017   Bugs Bunny    987-654-3210  Happy Birthdays Bugs Carrot         Carrot          Carrots 

到一个看起来像这样的数组:

var rowA = {PickupData:'4/16/2017',ClientName:'Bugs Bunny',Phone:'987-654-3210',CakeText:'Happy Birthday Bugs',CakeFlavor:'Carrot',FrostingFlavor:'Carrot', FruitFilling:'Carrots',LinkToPO:''}

现在,当您进入您的采购订单表格填写数据时,您将能够输入如下数据:

rowA[PickupData] 
rowA[ClientName] etc...

密钥来自列标题,值来自您自己的行。因此,列的顺序并不重要。稍后您可以通过更改列的名称来更改变量的名称。

您可以将其他信息作为字符串存储在file.setContent(&#39; string&#39;)中,然后将其与file.getBlob()。getDataAsString()。split(delimiter)和用你选择的任何分隔符拆分它。我经常选择你真正想要看到的那些奇怪的东西,比如&#39; | @@@ |&#39;。

你的最后一个问题是&#34;有没有人知道一个脚本,它允许我使用来自另一个特定行的数据填充新电子表格的特定单元格?&#34;这是对此的回答。对不起,我无法帮助你。

function copyToNewSS()
{
  var dstlocdict = {PickupDate:'A1',ClientName:'B2',Phone:'C3',CakeText:'D4',CakeFlavor:'E5',FrostingFlavor:'F6',FruitFilling:'G7',LinktoPO:'H8'}
  var srcss = SpreadsheetApp.getActiveSpreadsheet();
  var srcsht = srcss.getActiveSheet();
  var dstss = SpreadsheetApp.openById('Insert ID of Destination Spreadsheet');
  var dstsht = dstss.getSheetByName('PO');
  var srcrow = srcsht.getActiveCell().getRow();
  if((srcrow - 1)==0 || srcrow > srcsht.getLastRow()){SpreadsheetApp.getUi().alert('Error: Invalid Data Row');return;}
  var srcdatR = srcsht.getDataRange();
  var srcdatA = srcdatR.getValues();
  var srcdatdict = {};
  var srcnumcols = srcsht.getLastColumn();
  var s = '{';
  for(var i = 0;i < srcdatA[srcrow - 1].length; i++)
  {
    srcdatdict[srcdatA[0][i]]= srcdatA[srcrow-1][i];
    if(i>0)s += ', ';
    s += srcdatA[0][i] + ':' + srcdatA[srcrow-1][i];
  }
  myUtilities.dispStatus('Source Data Dictionary for Row ' + srcrow , s, 800, 400)  
  for(var key in srcdatdict)
  {
    dstsht.getRange(dstlocdict[key]).setValue(srcdatdict[key]); 
  }
}

答案 1 :(得分:0)

感谢Cooper的帮助。根据我的情况,我找到的最佳解决方案是编写绑定到PO模板的第二个脚本(及其重复项)。

绑定到CakeOrders数据库的第一个脚本继续按原样运行:触发后,它会创建PO模板的副本,根据原始行值命名,将其存储在指定的文件夹中,以及存储数据库中PO的URL。

我添加到PO模板(下面)的脚本允许用户填充基于原始行值的主体。

function onOpen() { 
var spreadsheet = SpreadsheetApp.getActive(); 
var menuItems = [ {name: 'Fill from Cake Order Form', functionName: 'FillInOrder'}]; 
spreadsheet.addMenu('Fill In Order', menuItems); 
    } 
//Creates drop down

function FillInOrder() { 
var orderSheet = SpreadsheetApp.openByUrl( 'https://docs.google.com/spreadsheets/d/1jX0bT2suuA-4nrYyXNrA5s9gtqxV7hmcgxeb5zUxOeQ/edit#gid=0'); 
var cakeOrders = orderSheet.getSheetByName('CakeOrders') 
var orderRow = Browser.inputBox('Fill from CakeOrders', 'Please enter the row number of the order to use' + ' (for example, "2"):', Browser.Buttons.OK_CANCEL); 
if (orderRow == 'cancel') { return; } var rowNumber = Number(orderRow); if (isNaN(rowNumber) || rowNumber < 2 || rowNumber > cakeOrders.getLastRow()) { 
Browser.msgBox('Error', Utilities.formatString('Row "%s" is not valid.', orderRow), Browser.Buttons.OK); 
return; 
    } 
//Prompts user for row
var pickupDate = cakeOrders.getRange(rowNumber,1).getValue(); 
var clientName = cakeOrders.getRange(rowNumber,2).getValue(); 
var textOnCake = cakeOrders.getRange(rowNumber,3).getValue(); 

var clientSheet = SpreadsheetApp.getActive().getSheetByName("Client"); 

//Gets values from source database

clientSheet.getRange("B8").setValue(pickupDate); 
clientSheet.getRange("B4").setValue(clientName); 
clientSheet.getRange("B12").setValue(textOnCake); 
}
//Sets values in new PO