검색
검색
공개 노트 검색
회원가입로그인

구글 스프레드 시트에서 공짜로 LLM 사용하기(심화-결과)

결국 이 코드만 살아 남았다.

전제 조건

A열에는 프롬프트를 적용할 글이, B1에는 프롬프트가, B2에는 서식(예: =gpt2(a2,$b$1)이 있어야 합니다.

주석은 1분 후로 되어 있지만 30초로 조정함

// 배치 작업: A열의 다음 10개 행에 수식을 입력하고, 1분 후 결과 처리를 위한 트리거를 등록
function processBatch() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var scriptProperties = PropertiesService.getScriptProperties();
  
  // 마지막 처리한 행 번호 (없으면 1, 즉 B2부터 시작)
  var lastProcessedRow = Number(scriptProperties.getProperty("lastProcessedRow")) || 1;
  var startRow = lastProcessedRow + 1;
  var batchSize = 10;
  
  // 이번 배치 대상: A열의 startRow ~ (startRow+batchSize-1)
  var dataRange = sheet.getRange("A" + startRow + ":A" + (startRow + batchSize - 1));
  var dataValues = dataRange.getValues();
  
  var rowsToProcess = 0;
  for (var i = 0; i < dataValues.length; i++) {
    if (dataValues[i][0] === "" || dataValues[i][0] === null) break;
    rowsToProcess++;
  }
  
  if (rowsToProcess === 0) {
    Logger.log("더 이상 처리할 데이터가 없습니다.");
    deleteTimeBasedTriggers();
    return;
  }
  
  // 이번 배치의 시작 행을 저장 (processResults에서 사용)
  scriptProperties.setProperty("currentBatchStartRow", startRow.toString());
  
  // B열 해당 범위에 대해 수식 입력 (B2는 처음 입력된 수식 그대로 유지)
  for (var i = 0; i < rowsToProcess; i++) {
    var rowNumber = startRow + i;
    var cell = sheet.getRange("B" + rowNumber);
    if (cell.getFormula() === "") {
      cell.setFormula("=gpt2(A" + rowNumber + ",$B$1)");
    }
  }
  
  // 이번 배치의 마지막 행 업데이트
  scriptProperties.setProperty("lastProcessedRow", (startRow + rowsToProcess - 1).toString());
  
  // 1분 후에 결과값으로 붙여넣기(수식을 값으로 전환)하는 작업을 위한 트리거 등록
  ScriptApp.newTrigger("processResults")
    .timeBased()
    .after(30000)
    .create();
  
  Logger.log("processBatch 실행: " + startRow + "행부터 " + (startRow+rowsToProcess-1) + "행까지 처리.");
}

// 1분 후 실행: 이번 배치의 수식을 결과값으로 고정한 후 다음 배치 실행을 예약
function processResults() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var scriptProperties = PropertiesService.getScriptProperties();
  
  var startRow = Number(scriptProperties.getProperty("currentBatchStartRow"));
  var lastProcessedRow = Number(scriptProperties.getProperty("lastProcessedRow"));
  var rowsToProcess = lastProcessedRow - startRow + 1;
  
  // 첫 배치일 경우(B2는 수식을 유지) B3부터 값 붙여넣기, 그 외 배치는 전체 범위 변환
  if (startRow === 2 && rowsToProcess > 1) {
    var convertRange = sheet.getRange("B" + (startRow + 1) + ":B" + lastProcessedRow);
    convertRange.setValues(convertRange.getValues());
  } else {
    var batchRange = sheet.getRange("B" + startRow + ":B" + lastProcessedRow);
    batchRange.setValues(batchRange.getValues());
  }
  
  // processResults 트리거 삭제 (방금 실행된 트리거)
  deleteTriggerByFunction("processResults");
  
  // 다음 배치 진행 여부 확인
  var nextRow = lastProcessedRow + 1;
  var nextValue = sheet.getRange("A" + nextRow).getValue();
  if (nextValue !== "" && nextValue !== null) {
    // 1초 후 다음 배치를 위한 processBatch 실행 트리거 등록
    ScriptApp.newTrigger("processBatch")
      .timeBased()
      .after(1000)
      .create();
    Logger.log("다음 배치 예약: " + nextRow + "행부터 실행 예정.");
  } else {
    Logger.log("모든 데이터를 처리했습니다.");
    deleteTimeBasedTriggers();
  }
}

// 지정된 함수 이름의 트리거(시간 기반 트리거)만 삭제
function deleteTriggerByFunction(functionName) {
  var triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() === functionName &&
        triggers[i].getTriggerSource() === ScriptApp.TriggerSource.CLOCK) {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}

// 모든 시간 기반(Clock) 트리거 삭제
function deleteTimeBasedTriggers() {
  var triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    if (triggers[i].getTriggerSource() === ScriptApp.TriggerSource.CLOCK) {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}
공유하기
카카오로 공유하기
페이스북 공유하기
트위터로 공유하기
url 복사하기
조회수 : 121
heart
T
페이지 기반 대답
AI Chat