2014-11-06 103 views
0

我在Google表格的廣闊報告中工作,但在我的工作流程中 我收到了直接發送給經理的電子郵件,但是當經理批准或拒絕請求時,我沒有收到包含該電子郵件的電子郵件直接發送給員工或請求者,但我需要手動運行onReportOrApprovalSubmit()函數。 我認爲有可能在觸發一個問題...建議我請谷歌表格費用審批報告

var APPROVALS_SPREADSHEET_ID = ""; 
var APPROVAL_FORM_URL = ; 
var STATE_MANAGER_EMAIL = "MANAGER_EMAIL"; 
var STATE_APPROVED = "APPROVED"; 
var STATE_DENIED = "DENIED"; 
var COLUMN_STATE = 5; 
var COLUMN_COMMENT = 7; 

// Main tutorial function: 
// For each row (expense report): 
// - if it's new, email the report to a manager for approval 
// - if it has recently been accepted or denied by a manager, email the results to the employee 
// - otherwise (expense reports that have already been fully processed or old expense reports 
//  that still have not been approved or rejected), do nothing 
// Ideally, this function would be run every time the Approvals Spreadsheet or the Expense Report 
// Spreadsheet are updated (via a Form submission) or regularly (once a day). 
function onReportOrApprovalSubmit() { 
    // This is the Expense Report Spreadsheet 
    var ss = SpreadsheetApp.getActiveSpreadsheet(); 
    var sheet = ss.getSheets()[0]; 

    // Also open the Approvals Spreadsheet 
    var approvalsSpreadsheet = SpreadsheetApp.openById(APPROVALS_SPREADSHEET_ID); 
    var approvalsSheet = approvalsSpreadsheet.getSheets()[0]; 

    // Fetch all the data from the Expense Report Spreadsheet 
    // getRowsData was reused from Reading Spreadsheet Data using JavaScript Objects tutorial 
    var data = getRowsData(sheet); 

    // Fetch all the data from the Approvals Spreadsheet 
    var approvalsData = getRowsData(approvalsSheet); 

    // For every expense report 
    for (var i = 0; i < data.length; ++i) { 
    var row = data[i]; 
    row.rowNumber = i + 2; 
    if (!row.state) { 
     // This is a new Expense Report. 
     // Email the manager to request his approval. 
     sendReportToManager(row); 
     // Update the state of the report to avoid email sending multiple emails 
     // to managers about the same report. 
     sheet.getRange(row.rowNumber, COLUMN_STATE).setValue(row.state); 
    } else if (row.state == STATE_MANAGER_EMAIL) { 
     // This expense report has already been submitted to a manager for approval. 
     // Check if the manager has accepted or rejected the report in the Approval Spreadsheet. 
     for (var j = 0; j < approvalsData.length; ++j) { 
     var approval = approvalsData[j]; 
     if (row.rowNumber != approval.expenseReportId) { 
      continue; 
     } 
     // Email the employee to notify the Manager's decision about the report. 
     sendApprovalResults(row, approval); 
     // Update the state of the report to APPROVED or DENIED 
     sheet.getRange(row.rowNumber, COLUMN_STATE).setValue(row.state); 
     break; 
     } 
    } 
    } 
} 

// Sends an email to an employee to communicate the manager's decision on a given Expense Report. 
function sendApprovalResults(row, approval) { 
    var approvedOrRejected = (approval.approveExpenseReport == "Yes") ? "approved" : "rejected"; 
    var message = "<HTML><BODY>" 
    + "<P>" + "PCS Manager" + " has " + approvedOrRejected + " your change report." 
+ "<P>" + "Report Id: " + row.rowNumber 
    + "<P>" + "Requester Name: " + row.name 
    + "<P>" + "Change Request Type: " + row.changeRequestType 
    + "<P>" + "Description: " + row.description 
    + "<P>" + "Justifications: " + row.justifications 
    + "<P>" + "Manager Approval Statues :" + (approval.approveExpenseReport || "") 

    + "<P>Base Points: " + (approval.basePoints || "") 
    + "<P>Cost($): " + (approval.cost || "") 
    + "<P>Manager's comment: " + (approval.comments || "") 
    + "</HTML></BODY>"; 
    MailApp.sendEmail(row.emailAddress, "Change Report Approval Results", "", {htmlBody: message}); 
    if (approval.approveExpenseReport == "Yes") { 
    row.state = STATE_APPROVED; 
    } else { 
    row.state = STATE_DENIED; 
    } 
} 

// Sends an email to a manager to request his approval of an employee expense report. 
function sendReportToManager(row) { 
    var message = "<HTML><BODY>" 
    + "<P>" + row.emailAddress + " has requested your approval for a change report." 
    + "<P>" + "Report Id: " + row.rowNumber 
    + "<P>" + "Requester Name: " + row.name 
    + "<P>" + "Change Request Type: " + row.changeRequestType 
    + "<P>" + "Description: " + row.description 
    + "<P>" + "Justifications: " + row.justifications 

    + '<P>Please approve or reject the change report <A HREF="' + APPROVAL_FORM_URL + '">here</A>.' 
    + "</HTML></BODY>"; 
    MailApp.sendEmail("[email protected]", "Change Report Approval Request", "", {htmlBody: message}); 
    row.state = STATE_MANAGER_EMAIL; 
} 





///////////////////////////////////////////////////////////////////////////////// 
// Code reused from Reading Spreadsheet Data using JavaScript Objects tutorial // 
///////////////////////////////////////////////////////////////////////////////// 

// getRowsData iterates row by row in the input range and returns an array of objects. 
// Each object contains all the data for a given row, indexed by its normalized column name. 
// Arguments: 
// - sheet: the sheet object that contains the data to be processed 
// - range: the exact range of cells where the data is stored 
//  This argument is optional and it defaults to all the cells except those in the first row 
//  or all the cells below columnHeadersRowIndex (if defined). 
// - columnHeadersRowIndex: specifies the row number where the column names are stored. 
//  This argument is optional and it defaults to the row immediately above range; 
// Returns an Array of objects. 
function getRowsData(sheet, range, columnHeadersRowIndex) { 
    var headersIndex = columnHeadersRowIndex || range ? range.getRowIndex() - 1 : 1; 
    var dataRange = range || 
    sheet.getRange(headersIndex + 1, 1, sheet.getMaxRows() - headersIndex, sheet.getMaxColumns()); 
    var numColumns = dataRange.getEndColumn() - dataRange.getColumn() + 1; 
    var headersRange = sheet.getRange(headersIndex, dataRange.getColumn(), 1, numColumns); 
    var headers = headersRange.getValues()[0]; 
    return getObjects(dataRange.getValues(), normalizeHeaders(headers)); 
} 

// For every row of data in data, generates an object that contains the data. Names of 
// object fields are defined in keys. 
// Arguments: 
// - data: JavaScript 2d array 
// - keys: Array of Strings that define the property names for the objects to create 
function getObjects(data, keys) { 
    var objects = []; 
    for (var i = 0; i < data.length; ++i) { 
    var object = {}; 
    var hasData = false; 
    for (var j = 0; j < data[i].length; ++j) { 
     var cellData = data[i][j]; 
     if (isCellEmpty(cellData)) { 
     continue; 
     } 
     object[keys[j]] = cellData; 
     hasData = true; 
    } 
    if (hasData) { 
     objects.push(object); 
    } 
    } 
    return objects; 
} 

// Returns an Array of normalized Strings. 
// Empty Strings are returned for all Strings that could not be successfully normalized. 
// Arguments: 
// - headers: Array of Strings to normalize 
function normalizeHeaders(headers) { 
    var keys = []; 
    for (var i = 0; i < headers.length; ++i) { 
    keys.push(normalizeHeader(headers[i])); 
    } 
    return keys; 
} 

// Normalizes a string, by removing all alphanumeric characters and using mixed case 
// to separate words. The output will always start with a lower case letter. 
// This function is designed to produce JavaScript object property names. 
// Arguments: 
// - header: string to normalize 
// Examples: 
// "First Name" -> "firstName" 
// "Market Cap (millions) -> "marketCapMillions 
// "1 number at the beginning is ignored" -> "numberAtTheBeginningIsIgnored" 
function normalizeHeader(header) { 
    var key = ""; 
    var upperCase = false; 
    for (var i = 0; i < header.length; ++i) { 
    var letter = header[i]; 
    if (letter == " " && key.length > 0) { 
     upperCase = true; 
     continue; 
    } 
    if (!isAlnum(letter)) { 
     continue; 
    } 
    if (key.length == 0 && isDigit(letter)) { 
     continue; // first character must be a letter 
    } 
    if (upperCase) { 
     upperCase = false; 
     key += letter.toUpperCase(); 
    } else { 
     key += letter.toLowerCase(); 
    } 
    } 
    return key; 
} 

// Returns true if the cell where cellData was read from is empty. 
// Arguments: 
// - cellData: string 
function isCellEmpty(cellData) { 
    return typeof(cellData) == "string" && cellData == ""; 
} 

// Returns true if the character char is alphabetical, false otherwise. 
function isAlnum(char) { 
    return char >= 'A' && char <= 'Z' || 
    char >= 'a' && char <= 'z' || 
    isDigit(char); 
} 

// Returns true if the character char is a digit, false otherwise. 
function isDigit(char) { 
    return char >= '0' && char <= '9'; 
} 

回答

0

從腳本轉到Resources -> Current Projects Triggers

添加一個新的觸發器來 -

RUNonReportOrApprovalSubmit時間 - 驅動 - 日定時器(上午8點 - 上午9點?)

您可以添加一個觸發器來運行onChange,但這會佔用正在發送的電子郵件。