Apps Script Code (doGet + doPost)
var SPREADSHEET_ID = '1V6a39FzkgLYYJXCqhWt3h2EG0OTE5p_AbClGhGo_dlc';
var MAIN_SHEET_GID = 928185651;
function doGet(e) {
var params = (e && e.parameter) ? e.parameter : {};
var ss = SpreadsheetApp.openById(SPREADSHEET_ID);
// action=saveMonthly / updateMonthly : บันทึก/แก้ไขข้อมูลรายเดือน
if (params.action === 'saveMonthly' || params.action === 'updateMonthly') {
// ใช้ GID เดียวกับการดึงข้อมูล — ไม่ขึ้นกับชื่อ sheet
var sheet = ss.getSheets().filter(function(s){ return s.getSheetId() == MAIN_SHEET_GID; })[0];
if (!sheet) return _json({ error: 'Main sheet not found (GID=' + MAIN_SHEET_GID + ')' });
// ตรวจหัวตาราง รองรับทั้งภาษาไทยและอังกฤษ
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]
.map(function(h){ return String(h).trim(); });
var iYear = _colIdx(headers, ['ปีงบประมาณ','year','Year','ปี']);
var iMonth = _colIdx(headers, ['เดือน','month','Month']);
var iLoc = _colIdx(headers, ['สถานที่','location','Location']);
var iKwh = _colIdx(headers, ['หน่วยที่ใช้','kwh','KWH','จำนวนหน่วย','หน่วย']);
var iThb = _colIdx(headers, ['จำนวนเงิน','thb','THB','ค่าไฟ']);
if (params.action === 'updateMonthly') {
// แก้ไข: หาแถวเดิมแล้วเขียนทับ
var allData = sheet.getDataRange().getValues();
var updated = false;
for (var r = 1; r < allData.length; r++) {
var rY = String(allData[r][iYear > 0 ? iYear - 1 : 0]).trim();
var rM = String(allData[r][iMonth > 0 ? iMonth - 1 : 1]).trim();
var rL = String(allData[r][iLoc > 0 ? iLoc - 1 : 2]).trim();
if (rY === String(params.year) && rM === String(params.month) && rL === String(params.location)) {
if (iKwh > 0) sheet.getRange(r + 1, iKwh).setValue(Number(params.kwh));
if (iThb > 0) sheet.getRange(r + 1, iThb).setValue(Number(params.thb));
updated = true;
break;
}
}
if (!updated) {
sheet.appendRow(_buildRow(headers.length, iYear, iMonth, iLoc, iKwh, iThb, params));
}
} else {
// บันทึกใหม่: append
sheet.appendRow(_buildRow(headers.length, iYear, iMonth, iLoc, iKwh, iThb, params));
}
SpreadsheetApp.flush();
return _json({ success: true, action: params.action, sheet: sheet.getName() });
}
// action=saveSubLoc : บันทึกหน่วยย่อยลงชีท จ.2 / จ.3 (ตาราง 2 มิติ)
if (params.action === 'saveSubLoc') {
var locType = String(params.locType || '').trim(); // 'jo2' หรือ 'jo3'
var sheetName = locType === 'jo2' ? 'จ.2' : 'จ.3';
var subSheet = ss.getSheetByName(sheetName);
if (!subSheet) return _json({ error: 'Sheet ' + sheetName + ' not found — กรุณาสร้าง sheet ชื่อ "' + sheetName + '" ก่อน' });
var entries = [];
try { entries = JSON.parse(params.entries || '[]'); } catch(err) { return _json({ error: 'parse entries failed' }); }
var month = String(params.month || '').trim(); // เช่น 'ต.ค.'
var savedCount = 0;
// อ่านหัวตาราง: แถว 1 (row index 0)
// คอลัมน์ A = ชื่อหน่วยงาน, B..M = เดือน
var allData = subSheet.getDataRange().getValues();
var headerRow = allData[0]; // ['สถานที่/เดือน', 'ต.ค.', 'พ.ย.', ...]
// หา column index ของเดือนที่ต้องการ (1-based สำหรับ GAS)
var colIdx = -1;
for (var c = 1; c < headerRow.length; c++) {
if (String(headerRow[c]).trim() === month) { colIdx = c + 1; break; } // +1 เพราะ GAS 1-based
}
if (colIdx < 0) return _json({ error: 'ไม่พบคอลัมน์เดือน "' + month + '" ใน sheet ' + sheetName });
// สร้าง map ชื่อหน่วยงาน → row number (1-based)
var nameToRow = {};
for (var r = 1; r < allData.length; r++) {
var cellName = String(allData[r][0]).trim();
if (cellName) nameToRow[cellName] = r + 1; // +1 เพราะ GAS 1-based
}
// บันทึกแต่ละ entry
entries.forEach(function(entry) {
var name = String(entry.name || '').trim();
var kwh = Number(entry.kwh) || 0;
if (!name || !kwh) return;
var rowNum = nameToRow[name];
if (!rowNum) {
// ถ้าไม่พบชื่อ → append แถวใหม่
var newRow = [];
for (var i = 0; i < headerRow.length; i++) newRow.push('');
newRow[0] = name;
newRow[colIdx - 1] = kwh;
subSheet.appendRow(newRow);
// อัปเดต map
nameToRow[name] = subSheet.getLastRow();
} else {
subSheet.getRange(rowNum, colIdx).setValue(kwh);
}
savedCount++;
});
SpreadsheetApp.flush();
return _json({ success: true, action: 'saveSubLoc', sheet: sheetName, month: month, saved: savedCount });
}
// ดึงข้อมูล
var sheetParam = params.sheet || '';
var sheet;
if (sheetParam === 'depart') {
sheet = ss.getSheetByName('depart');
if (!sheet) return _json({ error: 'Sheet depart not found' });
} else if (sheetParam === 'jo2' || sheetParam === 'jo3') {
// ดึงข้อมูลชีท จ.2 / จ.3 ตาราง 2 มิติ → แปลงเป็น {rows} format
var jSheet = ss.getSheetByName(sheetParam === 'jo2' ? 'จ.2' : 'จ.3');
if (!jSheet) return _json({ rows: {}, sheet: sheetParam, timestamp: new Date().toISOString() });
var jData = jSheet.getDataRange().getValues();
var jHeaders = jData[0]; // ['สถานที่/เดือน', 'ต.ค.', 'พ.ย.', ...]
var jResult = {}; // { 'ชื่อหน่วยงาน': { 'ต.ค.': 123, 'พ.ย.': 456, ... } }
for (var jr = 1; jr < jData.length; jr++) {
var jName = String(jData[jr][0]).trim();
if (!jName) continue;
jResult[jName] = {};
for (var jc = 1; jc < jHeaders.length; jc++) {
var jMon = String(jHeaders[jc]).trim();
var jVal = jData[jr][jc];
if (jMon && jVal !== '' && jVal !== null && !isNaN(Number(jVal))) {
jResult[jName][jMon] = Number(jVal);
}
}
}
return _json({ rows: jResult, sheet: sheetParam, timestamp: new Date().toISOString() });
} else if (sheetParam === 'construction') {
// ดึงเลขที่สัญญาจากชีท "งานก่อสร้าง" คอลัมน์ A
var cSheet = ss.getSheetByName('งานก่อสร้าง');
if (!cSheet) return _json({ colA: [], sheet: 'construction', timestamp: new Date().toISOString() });
var cData = cSheet.getDataRange().getValues();
var colA = [];
for (var cr = 1; cr < cData.length; cr++) {
var cVal = String(cData[cr][0]).trim();
if (cVal) colA.push(cVal);
}
return _json({ colA: colA, sheet: 'construction', timestamp: new Date().toISOString() });
} else {
}
var data = sheet.getDataRange().getValues();
var headers = data[0];
var rows = data.slice(1).filter(function(row){ return row.some(function(c){ return c !== ''; }); })
.map(function(row){ var obj={}; headers.forEach(function(h,i){ obj[h]=row[i]; }); return obj; });
return _json({ rows: rows, headers: headers, sheet: sheetParam||'main', timestamp: new Date().toISOString() });
}
function _colIdx(headers, candidates) {
for (var ci = 0; ci < candidates.length; ci++) {
var idx = headers.indexOf(candidates[ci]);
if (idx >= 0) return idx + 1;
}
return -1;
}
function _buildRow(len, iYear, iMonth, iLoc, iKwh, iThb, params) {
var row = [];
for (var i = 0; i < len; i++) row.push('');
if (iYear > 0) row[iYear - 1] = params.year;
if (iMonth > 0) row[iMonth - 1] = params.month;
if (iLoc > 0) row[iLoc - 1] = params.location;
if (iKwh > 0) row[iKwh - 1] = Number(params.kwh);
if (iThb > 0) row[iThb - 1] = Number(params.thb);
return row;
}
function doPost(e) { return doGet(e); }
function _json(obj) {
return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON);
}