구글 스프레드 시트에서 공짜로 LLM 사용하기(심화-코드)
기본을 작성한 적이 없는데 심화부터 작성합니다.
내용은 수시로 업데이트 될 예정입니다.
결과는 다음 글로 작성 예정입니다.
코드 작성 요청을 위한 프롬프트 작성
누군가 프롬프트를 더 최적화해 줄 수 있을 것이라 생각합니다.
Google 스프레드 시트 B열에 =gpt2(A854,$B$1) 와 같은 수식이 있어.
이 수식은 gpt2라는 앱스크립트를 가이드($B$1)에 따라 A854에 대한 작업을 수행해서 B열에 결과를 입력해줘.
Google api를 사용하기 때문에 한 번에 10개씩 작업을 수행해야 돼.
1. B열의 2번째 열에 처음으로 수식을 입력하면 =gpt2(A2,$B$1) 나머지 행에는 자동으로 10개씩 1분 간격으로 이 수식을 복사 붙여넣기 하고 싶어.
2. gpt2의 작업이 스트립트에 따라 끝나 B열에 값이 입력되면, B2는 제외한 B3부터 셀 값을 복사한 후 값만 붙여넣기 하고, 이전 10개 행 이후에 앞서 입력한 수식을 또 10개 행에 붙여 넣어야 해. 이전 작업에서 B11 셀에 =gpt2(A11,$B$1)이었으니 이번에는 B12부터 =gpt2(A12,$B$1) 를 이어나가야해.
3. A열에 값이 없다면 이 스크립트는 작업을 그만하고 싶어.
4. 이 작업을 수행하는 셀 상단에 도형을 넣고 이 스크립트를 실행하도록 만들거야.
5. A열에 새로운 값이 입력되어 예를 들어 A101부터 작업을 다시 수행한다면, B2의 수식을 다시 가져와서 B101부터 작업을 이어나가고, 다시 A열에 답이 없으면 스크립트가 정지되어야 해.Claude 제안 코드
이 코드는 실패할 것이라 생각합니다.
이 스크립트는 요청하신 모든 기능을 구현합니다. 주요 기능을 설명드리면:
10개씩 자동 처리:
processNextBatch함수가 한 번에 10개의 행을 처리합니다각 배치 사이에 1분 간격을 둡니다
값 복사 및 수식 진행:
B2를 제외한 이전 배치의 결과를 값으로 복사
다음 10개 행에 새로운 수식을 적용
빈 셀 감지:
findNextEmptyCell함수가 A열의 빈 셀을 감지하면 스크립트를 중지도형 연동:
assignToShape함수로 도형에 스크립트를 할당중단점에서 재시작:
A열에 새로운 값이 입력되면 해당 지점부터 작업 재개
사용 방법:
스크립트 편집기에서 이 코드를 붙여넣기
스프레드시트에 도형을 추가하고
assignToShape함수를 실행도형을 클릭하면 자동화가 시작됩니다
추가 기능이나 수정이 필요하시다면 말씀해 주세요.
function onOpen() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var menuItems = [
{name: 'Start GPT-2 Processing', functionName: 'startGPT2Processing'}
];
spreadsheet.addMenu('Custom Automation', menuItems);
}
function startGPT2Processing() {
var sheet = SpreadsheetApp.getActiveSheet();
// Find the first empty cell in column A
var startRow = findNextEmptyCell(sheet);
if (startRow === 2) {
// Start from beginning
processNextBatch(sheet, 2);
} else {
// Continue from where we left off
processNextBatch(sheet, startRow);
}
}
function findNextEmptyCell(sheet) {
var lastRow = sheet.getLastRow();
var columnA = sheet.getRange("A2:A" + lastRow).getValues();
for (var i = 0; i < columnA.length; i++) {
if (!columnA[i][0]) {
return i + 2; // Adding 2 because we start from row 2
}
}
return lastRow + 1;
}
function processNextBatch(sheet, startRow) {
var lastRow = sheet.getLastRow();
var endRow = Math.min(startRow + 9, lastRow); // Process 10 rows at a time
// Check if there's data to process
if (!sheet.getRange("A" + startRow).getValue()) {
Logger.log("No more data to process");
return;
}
// Apply GPT-2 formula to next 10 rows
var formulaRange = sheet.getRange("B" + startRow + ":B" + endRow);
var formulas = [];
for (var i = startRow; i <= endRow; i++) {
formulas.push(["=gpt2(A" + i + ",$B$1)"]);
}
formulaRange.setFormulas(formulas);
// Wait for 1 minute before processing the next batch
Utilities.sleep(60000);
// Copy values from previous batch (except B2)
if (startRow > 2) {
var previousRange = sheet.getRange("B" + (startRow) + ":B" + endRow);
previousRange.copyTo(previousRange, {contentsOnly: true});
}
// Schedule next batch
if (endRow < lastRow && sheet.getRange("A" + (endRow + 1)).getValue()) {
processNextBatch(sheet, endRow + 1);
}
}
// Function to assign script to a shape
function assignToShape() {
var sheet = SpreadsheetApp.getActiveSheet();
var shapes = sheet.getDrawings();
// Assuming the first shape should trigger the script
if (shapes.length > 0) {
shapes[0].assignScript('startGPT2Processing');
}
}ChatGPT 제안 코드(o3-mini-high)
코드 설명
마지막 처리된 행 관리
PropertiesService를 이용해 마지막으로 처리한 행 번호를 저장합니다.처음 실행 시엔 기본값 1을 사용하여 B2부터 시작하도록 합니다.
배치 처리
batchSize변수(여기서는 10)를 기준으로 A열의 데이터를 가져와, 값이 있는 행만 몇 개 처리할지 결정합니다.A열에 데이터가 없으면 스크립트가 중단됩니다.
수식 입력
해당 배치의 각 행에 대해 아직 수식이 없는 셀에
=gpt2(Ax,$B$1)형식의 수식을 입력합니다.최초 배치(B2)는 그대로 두고, 그 이후 배치부터 결과값을 고정하는 방식으로 진행합니다.
1분 대기 후 값 붙여넣기
Utilities.sleep(60000)으로 1분 대기 후, 현재 배치의 B열 셀의 결과값을 복사해 “값만 붙여넣기” 합니다.단, 첫 번째 배치는 B2의 수식을 유지합니다.
연속 작업
마지막으로 처리한 행 번호를 업데이트하고, A열의 다음 행에 데이터가 있으면 재귀 호출로 다음 배치를 실행합니다.
새로운 데이터가 추가되어 A열에 값이 나타나면, 이전 처리 상태를 기반으로 (B2의 수식을 참조하여) 이어서 작업됩니다.
도형에 스크립트 연결
이 스크립트를 저장한 후, 스프레드시트 상단에 도형을 추가하고 “스크립트 할당(Assign script)” 기능에 함수 이름
processBatch를 입력하면 도형 클릭 시 실행됩니다.이와 같이 작성하면 Google Sheets에서 gpt2 앱스크립트를 이용하여 한 번에 10개씩, 1분 간격으로 작업을 진행하고, 처리된 셀은 값으로 고정하여 이후의 연속 작업이 가능해집니다.
function processBatch() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var guide = sheet.getRange("B1").getValue();
// 마지막 처리 행 번호 기억
var scriptProperties = PropertiesService.getScriptProperties();
var lastProcessedRow = Number(scriptProperties.getProperty("lastProcessedRow")) || 1;
// 다음 배치의 시작 행 결정 (처음은 B2부터 시작)
var startRow = lastProcessedRow + 1;
// 한 번에 처리할 행 수 (10개)
var batchSize = 10;
// A열의 데이터를 가져옴
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("더 이상 처리할 데이터가 없습니다.");
return;
}
// B열의 해당 배치 범위 지정
var batchRange = sheet.getRange("B" + startRow + ":B" + (startRow + rowsToProcess - 1));
// 각 행에 수식 입력 (이미 수식이 없는 경우)
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)");
}
}
// 1분 대기 후 대기 중인 변경 사항 적용
Utilities.sleep(60000);
SpreadsheetApp.flush();
if (startRow === 2) {
// 첫 번째 배치일 경우, B2는 수식 그대로 두고 B3부터 값을 붙여넣기 처리
var firstBatchRange = sheet.getRange("B3:B" + (startRow + rowsToProcess - 1));
var firstBatchValues = firstBatchRange.getValues();
firstBatchRange.setValues(firstBatchValues);
} else {
// 그 다음 배치부터는 전체 범위를 값 붙여넣기 처리
batchRange.setValues(batchRange.getValues());
}
// 이번 배치의 마지막 행 번호 업데이트
scriptProperties.setProperty("lastProcessedRow", (startRow + rowsToProcess - 1));
// 다음 배치 실행 여부 확인
var nextRow = startRow + rowsToProcess;
var nextValue = sheet.getRange("A" + nextRow).getValue();
if (nextValue !== "" && nextValue !== null) {
processBatch();
} else {
Logger.log("모든 데이터를 처리했습니다.");
}
}DeepSeek 제안 코드
기능 설명
트리거 시작
시트 상단에 도형을 삽입하고
startProcessing함수를 할당합니다.도형 클릭 시 첫 번째 빈 행(
A열데이터 존재,B열빈칸)부터 처리 시작.10개 배치 처리
gpt2수식을 10개 행에 삽입하고 1분 후convertToValues함수가 실행되도록 트리거 설정.값으로 변환
1분 후 수식이 실행 완료되면 결과값을 고정값으로 변환하고 다음 배치 자동 처리.
자동 중단 조건
A열에 더 이상 데이터가 없거나 새 데이터가 추가되면 해당 위치에서 재개.에러 방지
동시 실행 방지, 트리거 자동 정리 등 안정성 강화.
설정 방법
스프레드시트 메뉴에서 확장 프로그램 > Apps Script 열기.
위 코드를 복사하여 스크립트 편집기에 붙여넣기.
스프레드시트에 도형을 삽입하고 도형에
startProcessing함수 연결.
B1셀에 가이드 텍스트 입력 후 테스트 실행.이 스크립트는 API 호출 제한을 준수하면서 자동으로 데이터를 처리하며, 사용자의 요구 사항을 모두 충족합니다.
function startProcessing() {
const scriptProperties = PropertiesService.getScriptProperties();
if (scriptProperties.getKeys().length > 0) return; // 이미 진행 중인 작업 방지
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const lastRow = sheet.getLastRow();
let startRow = null;
// A열에 데이터가 있고 B열이 비어 있는 첫 번째 행 찾기
for (let row = 2; row <= lastRow; row++) {
const aVal = sheet.getRange(`A${row}`).getValue();
const bVal = sheet.getRange(`B${row}`).getValue();
if (aVal !== "" && bVal === "") {
startRow = row;
break;
}
}
if (!startRow) {
console.log("처리할 데이터 없음");
return;
}
// 10개 행 배치 처리 (A열 데이터 유무 확인)
const batchRows = [];
for (let r = startRow; r < startRow + 10; r++) {
const aVal = sheet.getRange(`A${r}`).getValue();
if (aVal === "") break;
batchRows.push(r);
}
if (batchRows.length === 0) return;
// 수식 입력
const formulas = batchRows.map(row => [`=gpt2(A${row},$B$1)`]);
sheet.getRange(`B${batchRows[0]}:B${batchRows[batchRows.length - 1]}`).setFormulas(formulas);
// 트리거 및 상태 저장
scriptProperties.setProperty('lastStart', batchRows[0]);
scriptProperties.setProperty('lastEnd', batchRows[batchRows.length - 1]);
const trigger = ScriptApp.newTrigger('convertToValues').timeBased().after(60000).create();
scriptProperties.setProperty('triggerId', trigger.getUniqueId());
}
function convertToValues() {
const scriptProperties = PropertiesService.getScriptProperties();
const start = parseInt(scriptProperties.getProperty('lastStart'));
const end = parseInt(scriptProperties.getProperty('lastEnd'));
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (start < end) {
sheet.getRange(`B${start + 1}:B${end}`).setValues(sheet.getRange(`B${start + 1}:B${end}`).getValues());
}
// 트리거 정리
const triggerId = scriptProperties.getProperty('triggerId');
ScriptApp.getProjectTriggers().forEach(trigger => {
if (trigger.getUniqueId() === triggerId) ScriptApp.deleteTrigger(trigger);
});
scriptProperties.deleteAllProperties();
startProcessing(); // 다음 배치 처리
}
// 도형에 스크립트 연결 (도형 삽입 후 "startProcessing" 할당)