1. Buka Google Sheets Anda → klik menu
Extensions → Apps Script
2. ⚠️
Jika Anda SUDAH PERNAH setup sebelumnya (ada fungsi readSetting, getRecord, setupMindsetApp, dll), JANGAN hapus semua kode! Cukup cari fungsi
doPost(e) yang sudah ada, hapus fungsi itu saja, lalu tempel penggantinya di bawah ini (fungsi lain seperti
doGet,
readSetting,
setupMindsetApp,
jsonResponse dibiarkan seperti apa adanya):
function doPost(e) {
try {
const payload = JSON.parse(e.postData.contents);
const tes = (payload.tes || '').toUpperCase();
const sheetName = tes === 'NST' ? SHEET_NST : SHEET_TKD;
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(sheetName);
if (!sheet) sheet = ss.insertSheet(sheetName);
if (sheet.getLastRow() === 0 && payload.headers) {
sheet.appendRow(payload.headers);
const hr = sheet.getRange(1, 1, 1, payload.headers.length);
hr.setFontWeight('bold');
hr.setBackground('#D6E4F0');
sheet.setFrozenRows(1);
sheet.setColumnWidth(1, 160);
sheet.setColumnWidth(3, 180);
}
// Ambil header ASLI dari baris 1 sheet (bukan asumsi urutan dari klien) —
// ini membuat penulisan data KEBAL terhadap kolom yang disisipkan/diurutkan ulang manual.
const lastCol = Math.max(sheet.getLastColumn(), payload.headers ? payload.headers.length : 1);
const sheetHeaders = sheet.getLastRow() > 0
? sheet.getRange(1, 1, 1, lastCol).getValues()[0]
: (payload.headers || []);
// Susun baris baru dengan MEMETAKAN tiap field berdasarkan NAMA header
// (payload.headers[i] -> payload.values[i]), bukan berdasarkan posisi array.
// existingRow (opsional) dipertahankan untuk kolom yang tidak dikirim klien.
function petakanBarisByHeader(existingRow) {
const row = existingRow ? existingRow.slice() : new Array(sheetHeaders.length).fill('');
(payload.headers || []).forEach((h, i) => {
let col = sheetHeaders.indexOf(h);
if (col === -1) { sheetHeaders.push(h); col = sheetHeaders.length - 1; }
while (row.length <= col) row.push('');
row[col] = payload.values[i];
});
return row;
}
// MODE UPDATE (fitur Edit Data) — cari baris dg timestamp = row_key, lalu timpa
if (payload.mode === 'update' && payload.row_key && payload.values) {
const data = sheet.getDataRange().getValues();
const tsCol = sheetHeaders.indexOf('timestamp');
let rowIndex = -1;
if (tsCol > -1) {
for (let i = 1; i < data.length; i++) {
if (String(data[i][tsCol]) === String(payload.row_key)) { rowIndex = i + 1; break; }
}
}
if (rowIndex > 0) {
const newRow = petakanBarisByHeader(data[rowIndex - 1]);
sheet.getRange(rowIndex, 1, 1, newRow.length).setValues([newRow]);
return jsonResponse({ status: 'ok', sheet: sheetName, row: rowIndex, mode: 'updated' });
}
const newRow = petakanBarisByHeader(null);
sheet.appendRow(newRow);
return jsonResponse({ status: 'ok', sheet: sheetName, row: sheet.getLastRow(), mode: 'appended' });
}
if (payload.values) {
const newRow = petakanBarisByHeader(null);
sheet.appendRow(newRow);
}
return jsonResponse({ status: 'ok', sheet: sheetName, row: sheet.getLastRow() });
} catch(err) {
return jsonResponse({ status: 'error', message: err.message });
}
}
📦 Setup dari nol (belum pernah ada Apps Script)? Minta file lengkap "Google Apps Script v0.4" ke pengembang — berisi doGet (baca setting/data), doPost (simpan/update), dan setupMindsetApp() (isi otomatis sheet "setting", "HASIL_TKD", "HASIL_NST").
3. Klik
Deploy → Manage Deployments → klik ikon pensil (edit) pada deployment aktif → Version:
New version →
Deploy
4. (Kalau ini deployment pertama kali)
Deploy → New Deployment → Type:
Web App | Execute as:
Me | Access:
Anyone → copy URL → paste di kolom atas
5. Pertama kali: klik
Authorize access dan login akun Google Anda