1

도움을 주셔서 감사합니다.Google 시트 스크립트 - 셀 값을 찾으면 헤더 값 반환

첫 번째 행에 헤더 값이 포함 된 Google 시트가 있습니다. 나는 시트의 나머지 부분 (행 단위)을보고있는 스크립트를 가지고 있으며 셀이 특정 색상이라면 스크립트는 카운트를 유지합니다. 결국 카운트 수가 시트에 설정된 변수보다 크면 스크립트가 전자 메일을 트리거합니다.

스크립트에서 설정된 색상의 셀을 찾으면 열 머리글 값을 캡처하는 것이 무엇입니까? 나는 헤더 값을 가진 배열을 생성하고 위치를 비교할 필요가 있다고 확신한다. 그렇게 효율적으로하는 방법을 모르겠다.

function sendEmails() { 
    var ss = SpreadsheetApp.getActiveSpreadsheet(); 
    var dataSheet = ss.getSheets()[0]; 
    var lastRow = dataSheet.getLastRow(); 
    var lastColumn = dataSheet.getLastColumn(); 

    //Project Range Information 
    var projectRange = dataSheet.getRange(6,3,lastRow-5,lastColumn); 
    var projectRangeValues = projectRange.getValues()[0]; 
    var cellColors = projectRange.getBackgrounds(); 

    //Student Information Range 
    var studentRange = dataSheet.getRange(6,1,lastRow-5,lastColumn); 
    var studentRangeValues = studentRange.getValues(); 

    //Pull email template information 
    var emailSubject = ss.getRange("Variables!B1").getValue(); 
    var emailText = ss.getRange("Variables!B2").getValue(); 
    var triggerValue = ss.getRange("Variables!B4").getValue(); 
    var ccValue = ss.getRange("Variables!B5").getValue(); 

    //Where to Start and What to Check 
    var colorY = ss.getRange("Variables!B6").getValue(); 
    var count = 0; 
    var startRow = 6; 

    //Loop through sheet and pull data 
    for(var i = 0; i < cellColors.length; i++) { 
    //Pull some information from the rows to use in email 
    var studentName = studentRangeValues[i][0]; 
    var studentBlogUrl = studentRangeValues[i][1]; 
    var studentEmail = studentRangeValues[i][2]; 
    var studentData = [studentName,studentBlogUrl]; 

    //Loop through cell colors and count them 
    for(var j = 0; j < cellColors[0].length ; j++) { 
     if(cellColors[i][j] == colorY) { 

      /*This is where I feel I need to add the array comparisons to get the header values */ 

      count = count + 1; 
     };//end if statement 
    };//end for each cell in a row 

    //If the count is greater than trigger, send emails 
    if (count >= triggerValue) { 
     //A call to another function that merges the information    
     var emailBody = fillInTemplateFromObject(emailText, studentData); 
     MailApp.sendEmail({ 
      to: studentEmail, 
      cc: ccValue, 
      subject: emailSubject, 
      htmlBody: emailBody, 
     }); 
    } else {}; 
    //reset count to 0 before next row 
    count = 0; 
    };//end for each row 
}; 

편집 : 나는 응답을 기반으로 위의 코드 섹션을 업데이트 한 :

//Loop through cell colors and count them 
for(var j = 0; j < cellColors[0].length ; j++) { 
    if(cellColors[i][j] == colorY) { 
     //This pushes the correct information into the array that matches up with the columns with a color. 
     missingAssignments.push(headervalues[i][j]); 
     count = count + 1; 
    };//end if statement 
};//end for each cell in a row 

내가 문제를 :에서

//Header Information 
var headers = dataSheet.getRange(4,4,1,lastColumn); 
var headerValues = headers.getValues(); 
var missingAssignments = new Array(); 

내가 추가 한 루프의 실행 중 오류가 발생했습니다 - TypeError : 정의되지 않은 "2"속성을 읽을 수 없습니다. 이것은 스크립트가 다음 행으로 이동함에 따라 for 루프를 밀어 넣음으로써 발생합니다. 왜이 오류가 발생하는지 확신 할 수 없습니다. 읽은 다른 것들로부터 배열은 정의되지 않은 것으로 설정됩니다. 내가 배열을 비우려고 노력하고 그것의 길이를 0으로 설정했지만 도움이되지 않습니다. 나는 그것이 끝날 때 배열의 유효 범위를 이해하지 못한다고 생각합니다.

편집 : "i"가 반복해서는 안됩니다. 읽어야합니다 :

missingAssignments.push(headervalues[0][j]); 

첫 번째 for 루프의 끝 나는 다음 행의 배열을 지 웁니다.

missingAssignments.length = 0; 

답변

0

전체 시트의 값을 얻어야합니다. 그런 다음 shift 메서드를 사용하여 헤더 만 가져옵니다. 나는 당신의 시트에 대한 더 이상의 정보없이 당신의 의도를 완전히 이해하기가 어렵습니다. 더 많은 정보를 제공 할 수 있는지 알려주십시오.

function sendEmails() { 
    var ss = SpreadsheetApp.getActiveSpreadsheet(); 
    var dataSheet = ss.getSheets()[0]; 
    var lastRow = dataSheet.getLastRow(); 
    var lastColumn = dataSheet.getLastColumn(); 
    //below gets the whole sheet and shifts off the first row as headers 
    var fullSheet = dataSheet.getDataRange().getValues(); 
    var headers = fullSheet.shift(); 

    //then in your loops you can check against the index of the headers array 
+0

안녕하세요, 귀하의 답변에 감사드립니다. 그것은 옳은 길로 나를 잡았고 나의 헤더가 1 번 행에 있다면 이것이 완벽 할 것입니다. 시트를 업데이트해야하고 필요한 헤더 정보가 다른 행으로 끝납니다. 나는 몇몇 코드를 업데이트했다. 왜 내가 TypeError를 얻었을지 안다면 궁금해 하던가 ?? –

+0

알았어 두 번째 변수에 iterating했다. –

+0

필자는 완전히 확신 할 수는 없지만 getValues에서 반환되는 값은 항상 다차원 배열이기 때문에 그럴 것이라고 생각합니다. 다음과 같이해야합니다. var headerValues ​​= headers.getValues ​​() [0]; –

0

Apps 스크립트가있는 스프레드 시트는 특히 많은 양의 데이터를 읽을 때 매우 느립니다.

확인이 tips from Apps doc :

를 사용하여 일괄 작업

Scripts commonly need to read in data from a spreadsheet, perform calculations, and then write out the results of the data to a spreadsheet. Google Apps Script already has some built-in optimization, such as using look-ahead caching to retrieve what a script is likely to get and write caching to save what is likely to be set.

You can write scripts to take maximum advantage of the built-in caching, by minimizing the number of reads and writes. Alternating read and write commands is slow. To speed up a script, read all data into an array with one command, perform any operations on the data in the array, and write the data out with one command.

Here's an example — an example you should not follow or use. The Spreadsheet Fractal Art script in the Gallery (only available in the older version of Google Sheets) uses the following code to set the background colors of every cell in a 100 x 100 spreadsheet grid:

// DO NOT USE THIS CODE. It is an example of SLOW, INEFFICIENT code. 
// FOR DEMONSTRATION ONLY 
var cell = sheet.getRange('a1'); 
for (var y = 0; y < 100; y++) { 
    xcoord = xmin; 
    for (var x = 0; x < 100; x++) { 
    var c = getColor_(xcoord, ycoord); 
    cell.offset(y, x).setBackgroundColor(c); 
    xcoord += xincrement; 
    } 
    ycoord -= yincrement; 
    SpreadsheetApp.flush(); 
} 

The script is inefficient: it loops through 100 rows and 100 columns, writing consecutively to 10,000 cells. The Google Apps Script write-back cache helps, because it forces a write-back using flush at the end of every line. Because of the caching, there are only 100 calls to the Spreadsheet.

But the code can be made much more efficient by batching the calls. Here's a rewrite in which the cell range is read into an array called colors, the color assignment operation is performed on the data in the array, and the values in the array are written out to the spreadsheet:

// OKAY TO USE THIS EXAMPLE or code based on it. 
var cell = sheet.getRange('a1'); 
var colors = new Array(100); 
for (var y = 0; y < 100; y++) { 
    xcoord = xmin; 
    colors[y] = new Array(100); 
    for (var x = 0; x < 100; x++) { 
    colors[y][x] = getColor_(xcoord, ycoord); 
    xcoord += xincrement; 
    } 
    ycoord -= yincrement; 
} 

    sheet.getRange(1, 1, 100, 100).setBackgroundColors(colors); 

inefficient code takes about 70 seconds to run. The efficient code runs in just 1 second!

If you're looking at the Spreadsheet Fractal Art script (only available in the older version of Google Sheets), please be aware that we made a minor change to it to make this example easier to follow. The script as published uses the setBackgroundRGB call, rather than setBackgroundColor, which you see above. The getColor_ function was changed as follows:

if (iteration == max_iteration) { 
    return '#000000'; 
} else { 
    var c = 255 - (iteration * 5); 
    c = Math.min(255, Math.max(0, c)); 
    var hex = Number(c).toString(16); 
    while (hex.length < 2) 
    hex = '0' + hex; 

    return ('#' + hex + '3280'); 
} 
관련 문제