/** * GL Accounts refresh — Office Script for Excel Web. * * Setup: * 1. Start the Python API: uvicorn main:app --port 8000 * 2. Expose via ngrok: ngrok http 8000 * 3. Paste the ngrok URL in API_BASE below. * 4. In Excel Web: Automate tab > New Script > paste > Save > Run. * * Sheet layout (GL_Accounts_Client_Template.xlsx): * Setup!B6 = Company Functions!C6 = get_account_base_amount * Setup!B7 = Account Functions!C7 = get_account_real_base_amount * Setup!B8 = Currency Functions!C8 = get_account_amount * Setup!B9 = Date Functions!C9 = get_account_abbr * Functions!C10 = get_account_name * Functions!C11 = get_account_contact * Functions!C12 = get_account_contact_code * Functions!C13 = get_account_contact_name */ interface GlResults { get_account_base_amount: number; get_account_real_base_amount: number; get_account_amount: number; get_account_abbr: string; get_account_name: string; get_account_contact: string; get_account_contact_code: string; get_account_contact_name: string; } interface GlResponse { results: GlResults; errors: { [key: string]: string }; } async function main(workbook: ExcelScript.Workbook): Promise { // ── CONFIG ───────────────────────────────────────────────────────────────── const API_BASE = "https://obscure-boggle-sprig.ngrok-free.dev"; // ─────────────────────────────────────────────────────────────────────────── const setupSheet = workbook.getWorksheet("Setup"); const functionsSheet = workbook.getWorksheet("Functions"); if (!setupSheet || !functionsSheet) { console.log("Error: 'Setup' or 'Functions' sheet not found."); return; } const company: string = String(setupSheet.getRange("B6").getValue()); const account: string = String(setupSheet.getRange("B7").getValue()); const currency: string = String(setupSheet.getRange("B8").getValue()); const date: string = toIsoDate(setupSheet.getRange("B9").getValue()); // Mark as loading for (let row = 6; row <= 13; row++) { functionsSheet.getRange("C" + row).setValue("..."); } const url = API_BASE + "/gl/all" + "?company=" + encodeURIComponent(company) + "&account=" + encodeURIComponent(account) + "¤cy=" + encodeURIComponent(currency) + "&date=" + encodeURIComponent(date); let data: GlResponse; try { const response = await fetch(url, { headers: { "ngrok-skip-browser-warning": "true" } }); if (!response.ok) { throw new Error("HTTP " + response.status); } data = (await response.json()) as GlResponse; } catch (err) { console.log("API call failed: " + err); for (let row = 6; row <= 13; row++) { functionsSheet.getRange("C" + row).setValue("#API_ERROR"); } return; } const r = data.results; functionsSheet.getRange("C6").setValue(r.get_account_base_amount !== null ? r.get_account_base_amount : ""); functionsSheet.getRange("C7").setValue(r.get_account_real_base_amount !== null ? r.get_account_real_base_amount : ""); functionsSheet.getRange("C8").setValue(r.get_account_amount !== null ? r.get_account_amount : ""); functionsSheet.getRange("C9").setValue(r.get_account_abbr !== null ? r.get_account_abbr : ""); functionsSheet.getRange("C10").setValue(r.get_account_name !== null ? r.get_account_name : ""); functionsSheet.getRange("C11").setValue(r.get_account_contact !== null ? r.get_account_contact : ""); functionsSheet.getRange("C12").setValue(r.get_account_contact_code !== null ? r.get_account_contact_code : ""); functionsSheet.getRange("C13").setValue(r.get_account_contact_name !== null ? r.get_account_contact_name : ""); console.log("Refreshed: " + company + " / " + account + " / " + currency + " / " + date); } function toIsoDate(value: string | number | boolean): string { if (typeof value === "number") { // Excel date serial → YYYY-MM-DD const d = new Date(Date.UTC(1899, 11, 30) + value * 86400000); return d.toISOString().split("T")[0]; } const s = String(value); const d = new Date(s); if (!isNaN(d.getTime())) { return d.toISOString().split("T")[0]; } return s; }