diff --git a/README.md b/README.md index c4867f3..56990b5 100644 --- a/README.md +++ b/README.md @@ -73,4 +73,4 @@ Clone the repository, run the sample, and explore how Syncfusion React Spreadshe > A free community license is also available for companies and individuals whose organizations have less than $1 million USD in annual gross revenue and five or fewer developers: https://www.syncfusion.com/products/communitylicense. -See the LICENSE FILE at: https://github.com/syncfusion/ej2-javascript-ui-controls/blob/master/license for more details. \ No newline at end of file +See the LICENSE FILE at: https://github.com/syncfusion/ej2-javascript-ui-controls/blob/master/license for more details. diff --git a/index.html b/index.html index d625ef0..53beb49 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - + my-app diff --git a/package.json b/package.json index 8cf1978..7f198ec 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,14 @@ "react-dom": "^19.2.0" }, "devDependencies": { - "@eslint/js": "^9.39.1", - "@types/react": "^19.2.7", + "@eslint/js": "^9.39.4", + "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "eslint": "^9.39.1", + "@vitejs/plugin-react": "^6.0.1", + "eslint": "^9.39.4", "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", - "globals": "^16.5.0", - "vite": "^7.3.1" + "eslint-plugin-react-refresh": "^0.5.2", + "globals": "^17.4.0", + "vite": "^8.0.1" } } diff --git a/src/App.css b/src/App.css index b9d355d..c5f656f 100644 --- a/src/App.css +++ b/src/App.css @@ -1,42 +1,10 @@ -#root { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} +@import '../node_modules/@syncfusion/ej2-base/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-lists/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-popups/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-grids/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-react-spreadsheet/styles/material.css'; \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index 48c780f..a7f1224 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,265 +1,477 @@ import * as React from 'react'; import { createRoot } from 'react-dom/client'; -import { CellDirective, CellsDirective, ColumnDirective, ColumnsDirective, getColumnHeaderText, getSheet, RangeDirective, RangesDirective, RowDirective, RowsDirective, SheetDirective, SheetsDirective, SpreadsheetComponent, -} from '@syncfusion/ej2-react-spreadsheet'; -import { budgetSheets, actualSheets } from './dataSource'; -import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns'; +import { CellDirective, CellsDirective, RowDirective, RowsDirective, SheetDirective, SheetsDirective, SpreadsheetComponent, getSheet } from '@syncfusion/ej2-react-spreadsheet'; +import './App.css'; export default function App() { let spreadsheet; - const [year, setYear] = React.useState('2025'); - const yearList = [{ year: '2021' }, { year: '2022' }, { year: '2023' }, { year: '2024' }, { year: '2025' }]; - const fields = { text: 'year' }; - const onYearChange = (args) => { - const selectedYear = args.itemData.year; - setYear(selectedYear); + let budgetData = [ + { "Region": "South", "Branch": "Chennai", "Card Type": "Platinum", "Cards Issued": 2000, "Activation %": 0.80, "Average Spend": 450, "Revolving %": 0.40, "Interest %": 0.36 }, + { "Region": "South", "Branch": "Chennai", "Card Type": "Gold", "Cards Issued": 3000, "Activation %": 0.75, "Average Spend": 410, "Revolving %": 0.35, "Interest %": 0.32 }, + { "Region": "South", "Branch": "Chennai", "Card Type": "Classic", "Cards Issued": 2500, "Activation %": 0.70, "Average Spend": 395, "Revolving %": 0.30, "Interest %": 0.30 }, + { "Region": "South", "Branch": "Coimbatore", "Card Type": "Platinum", "Cards Issued": 1400, "Activation %": 0.78, "Average Spend": 445, "Revolving %": 0.38, "Interest %": 0.35 }, + { "Region": "South", "Branch": "Coimbatore", "Card Type": "Gold", "Cards Issued": 2000, "Activation %": 0.72, "Average Spend": 355, "Revolving %": 0.34, "Interest %": 0.32 }, + { "Region": "South", "Branch": "Coimbatore", "Card Type": "Classic", "Cards Issued": 2500, "Activation %": 0.70, "Average Spend": 390, "Revolving %": 0.30, "Interest %": 0.30 }, + { "Region": "South", "Branch": "Madurai", "Card Type": "Platinum", "Cards Issued": 1200, "Activation %": 0.76, "Average Spend": 340, "Revolving %": 0.36, "Interest %": 0.34 }, + { "Region": "South", "Branch": "Madurai", "Card Type": "Gold", "Cards Issued": 1500, "Activation %": 0.65, "Average Spend": 360, "Revolving %": 0.38, "Interest %": 0.34 }, + { "Region": "South", "Branch": "Madurai", "Card Type": "Classic", "Cards Issued": 1100, "Activation %": 0.60, "Average Spend": 385, "Revolving %": 0.32, "Interest %": 0.31 }, + { "Region": "South", "Branch": "Trichy", "Card Type": "Platinum", "Cards Issued": 1800, "Activation %": 0.78, "Average Spend": 450, "Revolving %": 0.42, "Interest %": 0.37 }, + { "Region": "South", "Branch": "Trichy", "Card Type": "Gold", "Cards Issued": 900, "Activation %": 0.70, "Average Spend": 410, "Revolving %": 0.35, "Interest %": 0.33 }, + { "Region": "South", "Branch": "Trichy", "Card Type": "Classic", "Cards Issued": 700, "Activation %": 0.62, "Average Spend": 390, "Revolving %": 0.28, "Interest %": 0.29 }, + { "Region": "West", "Branch": "Pune", "Card Type": "Platinum", "Cards Issued": 1600, "Activation %": 0.74, "Average Spend": 345, "Revolving %": 0.36, "Interest %": 0.33 }, + { "Region": "West", "Branch": "Pune", "Card Type": "Gold", "Cards Issued": 2200, "Activation %": 0.72, "Average Spend": 410, "Revolving %": 0.33, "Interest %": 0.31 }, + { "Region": "West", "Branch": "Pune", "Card Type": "Classic", "Cards Issued": 1400, "Activation %": 0.68, "Average Spend": 395, "Revolving %": 0.30, "Interest %": 0.29 }, + { "Region": "North", "Branch": "Delhi", "Card Type": "Platinum", "Cards Issued": 2100, "Activation %": 0.77, "Average Spend": 455, "Revolving %": 0.43, "Interest %": 0.36 }, + { "Region": "North", "Branch": "Delhi", "Card Type": "Gold", "Cards Issued": 1900, "Activation %": 0.70, "Average Spend": 315, "Revolving %": 0.34, "Interest %": 0.32 }, + { "Region": "North", "Branch": "Delhi", "Card Type": "Classic", "Cards Issued": 2700, "Activation %": 0.68, "Average Spend": 400, "Revolving %": 0.29, "Interest %": 0.28 }, + { "Region": "South", "Branch": "Kochi", "Card Type": "Platinum", "Cards Issued": 1000, "Activation %": 0.70, "Average Spend": 440, "Revolving %": 0.34, "Interest %": 0.32 }, + { "Region": "South", "Branch": "Kochi", "Card Type": "Gold", "Cards Issued": 1300, "Activation %": 0.67, "Average Spend": 405, "Revolving %": 0.32, "Interest %": 0.30 }, + { "Region": "South", "Branch": "Kochi", "Card Type": "Classic", "Cards Issued": 1600, "Activation %": 0.66, "Average Spend": 395, "Revolving %": 0.31, "Interest %": 0.29 }, + { "Region": "South", "Branch": "Bengaluru", "Card Type": "Platinum", "Cards Issued": 2400, "Activation %": 0.82, "Average Spend": 460, "Revolving %": 0.44, "Interest %": 0.38 }, + { "Region": "South", "Branch": "Bengaluru", "Card Type": "Gold", "Cards Issued": 2100, "Activation %": 0.78, "Average Spend": 330, "Revolving %": 0.36, "Interest %": 0.34 }, + { "Region": "South", "Branch": "Bengaluru", "Card Type": "Classic", "Cards Issued": 1800, "Activation %": 0.70, "Average Spend": 305, "Revolving %": 0.33, "Interest %": 0.31 }, + { "Region": "East", "Branch": "Kolkata", "Card Type": "Platinum", "Cards Issued": 1500, "Activation %": 0.75, "Average Spend": 445, "Revolving %": 0.38, "Interest %": 0.35 }, + { "Region": "East", "Branch": "Kolkata", "Card Type": "Gold", "Cards Issued": 2000, "Activation %": 0.70, "Average Spend": 410, "Revolving %": 0.34, "Interest %": 0.33 }, + { "Region": "East", "Branch": "Kolkata", "Card Type": "Classic", "Cards Issued": 1700, "Activation %": 0.69, "Average Spend": 400, "Revolving %": 0.30, "Interest %": 0.29 }, + { "Region": "West", "Branch": "Mumbai", "Card Type": "Platinum", "Cards Issued": 2300, "Activation %": 0.79, "Average Spend": 360, "Revolving %": 0.41, "Interest %": 0.37 }, + { "Region": "West", "Branch": "Mumbai", "Card Type": "Gold", "Cards Issued": 2500, "Activation %": 0.76, "Average Spend": 420, "Revolving %": 0.35, "Interest %": 0.34 }, + { "Region": "West", "Branch": "Mumbai", "Card Type": "Classic", "Cards Issued": 1900, "Activation %": 0.70, "Average Spend": 405, "Revolving %": 0.32, "Interest %": 0.30 } + ]; + + const actionBegin = (args) =>{ + console.log(args); + } + + const actionComplete = (args) =>{ + console.log(args); + } + + const columnLetterToIndex = (letters) => { + let index = 0; + for (let i = 0; i < letters.length; i++) { + index = index * 26 + (letters.charCodeAt(i) - 64); + } + return index; + }; + + const onCellSave = (args) => { + const address = args.address || args.range || ''; + if (!address) return; + const [sheetPart, cellPart] = address.includes('!') ? address.split('!') : ['BudgetSheet', address]; + if (sheetPart.toLowerCase() === 'budgetsheet') { + const m = (cellPart || '').match(/([A-Z]+)(\d+)/i); + if (!m) return; + const colLetters = m[1].toUpperCase(); + const row = parseInt(m[2], 10); + const colIndex = columnLetterToIndex(colLetters); + if (colIndex < 1 || colIndex > 9) { + return; + } + spreadsheet.setBorder({ border: '1px solid #000000' }, `BudgetSheet!A${row}:L${row}`, 'Vertical'); + spreadsheet.addDataValidation({ type: 'List', value1: 'North,South,East,West', ignoreBlank: false }, `budgetSheet!B${row}`); + const jFormula = `=E${row}*F${row}*G${row}`; + const kFormula = `=J${row}*H${row}`; + const lFormula = `=K${row}*I${row}`; + spreadsheet.updateCell({ formula: jFormula }, `budgetSheet!J${row}`); + spreadsheet.updateCell({ formula: kFormula }, `budgetSheet!K${row}`); + spreadsheet.updateCell({ formula: lFormula }, `budgetSheet!L${row}`); + spreadsheet.cellFormat({ backgroundColor: '#CDE5E7' }, `budgetSheet!C${row} E${row} G${row} I${row} K${row}`); + if(colIndex == 9){ + for (let i = 4; i < row; i++) { + spreadsheet.updateCell({ formula: `=SUMIFS(budgetSheet!J4:J33, budgetSheet!C4:C33, Variance!B${i}, budgetSheet!D4:D33, Variance!C${i})` }, `Variance!D${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!G4:G1000, actuals!C4:C1000, Variance!B1000, actuals!D4:D1000, Variance!C${i})` }, `Variance!E${i}`); + spreadsheet.updateCell({ formula: `=Variance!D${i} - Variance!E${i}` }, `Variance!F${i}`); + spreadsheet.updateCell({ formula: `=Variance!F${i} / Variance!D${i}` }, `Variance!G${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(budgetSheet!L4:L33, budgetSheet!C4:C33, Variance!B${i}, budgetSheet!D4:D33, Variance!C${i})` }, `Variance!H${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!K4:K1000, actuals!C4:C1000, Variance!B${i}, actuals!D4:1000, Variance!C${i})` }, `Variance!I${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!H4:H1000,actuals!C4:C1000,Variance!B${i}, actuals!D4:D1000, Variance!C${i},actuals!L4:L1000,"Yes")/SUMIFS(actuals!H4:H1000,actuals!C4:C1000,Variance!B${i}, actuals!D4:D1000 , Variance!C${i})` }, `Variance!J${i}`); + //spreadsheet.updateCell({ formula: `=(Variance!E${i}/10)*30` }, `Variance!K${i}`); + spreadsheet.updateCell({ formula: `=(budgetSheet!H${i}*0.4)+(Variance!J${i}*0.6)` }, `Variance!K${i}`); + spreadsheet.updateCell({ formula: `=IF(Variance!K${i}>0.30,"High Risk",IF(Variance!K${i}>0.20,"Moderate Risk","Low Risk"))` }, `Variance!L${i}`); + } + } + return; + } + if (sheetPart.toLowerCase() === 'actuals') { + // supports single cell or range like B4 or B4:G10 + const r = (cellPart || '').match(/^([A-Z]+)(\d+)(:([A-Z]+)(\d+))?$/i); + if (!r) return; + const startRow = parseInt(r[2], 10); + const endRow = r[5] ? parseInt(r[5], 10) : startRow; + for (let rr = startRow; rr <= endRow; rr++) { + // read Branch (col C) and Card_Type (col D) from the sheet model if available + let branchVal, cardTypeVal , outstandingBalance , transactionAmt; + try { + const sheetModel = getSheet(spreadsheet, 2); + const rowIndex = rr - 1; // sheetModel rows are 0-based + // In your actuals layout startCell 'B3' => columns: B=Date, C=Branch, D=Card_Type, E=Card_ID, F=Transaction_Amount, G=Revolving_Flag, H=Interest_Charged + branchVal = sheetModel.rows?.[rowIndex]?.cells?.[2]?.value; // C => index 2 + cardTypeVal = sheetModel.rows?.[rowIndex]?.cells?.[3]?.value; // D => index 3 + outstandingBalance = sheetModel.rows?.[rowIndex]?.cells?.[4]?.value; + transactionAmt = sheetModel.rows?.[rowIndex]?.cells?.[5]?.value; + } catch (e) { + // fallback: try reading visible DOM cell text + const cellC = spreadsheet.getCell?.({ rowIndex: rr - 1, colIndex: 2 }); // C + const cellD = spreadsheet.getCell?.({ rowIndex: rr - 1, colIndex: 3 }); // D + branchVal = branchVal || (cellC && cellC.innerText); + cardTypeVal = cardTypeVal || (cellD && cellD.innerText); + } + // compute rate and update H cell (Interest_Charged). Use a formula so it recalculates if F/G change. + const rate = getInterestRate(String(branchVal || '').trim(), String(cardTypeVal || '').trim()) || 0; + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'Yes', range: `actuals!G${startRow}`, cFColor: 'RedT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'No', range: `actuals!G${startRow}`, format: { style: { color: 'Green' } } }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'Yes', range: `actuals!I${startRow}`, cFColor: 'RedFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'No', range: `actuals!I${startRow}`, cFColor: 'GreenFT' }); + spreadsheet.setBorder({ border: '1px solid #000000' }, `actuals!B${startRow}:I${startRow}`, 'Vertical'); + //minimum due + spreadsheet.updateCell({ formula: `=(actuals!F${startRow} * 0.40` },`actuals!G${startRow}`); + //paid minimum + spreadsheet.updateCell({ formula: `=IF(AND(actuals!H${startRow} >=actuals!G${startRow},actuals!H${startRow} > 0),"Yes","No")` }, `actuals!I${startRow}`); + //isCarryOver + spreadsheet.updateCell({ formula: `=IF(actuals!F${startRow}-H${startRow} > 0,"Yes","No")` }, `actuals!J${startRow}`); + //Interest amount + spreadsheet.updateCell({ formula: `=(actuals!F${startRow}-H${startRow})*${rate}` }, `actuals!K${startRow}`); + //isLate + spreadsheet.updateCell({formula:`=IF(AND(actuals!F${startRow} > 0,actuals!I${startRow}="No"),"Yes","No")`},`actuals!L${startRow}`); + //calculate variance sheet + const col = r[1].toUpperCase(); + if (col == 'H') { + for (let i = 4; i < 33; i++) { + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!G4:G${startRow}, actuals!C4:C${startRow}, Variance!B${i}, actuals!D4:D${startRow}, Variance!C${i})` }, `Variance!E${i}`); + spreadsheet.updateCell({ formula: `=Variance!D${i} - Variance!E${i}` }, `Variance!F${i}`); + spreadsheet.updateCell({ formula: `=Variance!F${i} / Variance!D${i}` }, `Variance!G${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(budgetSheet!L4:L33, budgetSheet!C4:C33, Variance!B${i}, budgetSheet!D4:D33, Variance!C${i})` }, `Variance!H${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!K4:K${startRow}, actuals!C4:C${startRow}, Variance!B${i}, actuals!D4:D${startRow}, Variance!C${i})` }, `Variance!I${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!H4:H${startRow},actuals!C4:C${startRow},Variance!B${i}, actuals!D4:D${startRow} , Variance!C${i},actuals!L4:L${startRow},"Yes")/SUMIFS(actuals!H4:H${startRow},actuals!C4:C${startRow},Variance!B${i}, actuals!D4:D${startRow} , Variance!C${i})` }, `Variance!J${i}`); + spreadsheet.updateCell({ formula: `=(budgetSheet!H${i}*0.4)+(Variance!J${i}*0.6)` }, `Variance!K${i}`); + spreadsheet.updateCell({ formula: `=IF(Variance!K${i}>0.30,"High Risk",IF(Variance!K${i}>0.20,"Moderate Risk","Low Risk"))` }, `Variance!L${i}`); + } + } + } + } + }; + + const onCreated = () => { + spreadsheet.updateRange({ dataSource: budgetData, startCell: 'budgetSheet!B3' }, 1); + spreadsheet.setColumnsWidth(135, ['budgetSheet!B:L']); + spreadsheet.setColumnsWidth(130, ['budgetSheet!B:L', 'actuals!B:L', 'Variance!B:M']); + spreadsheet.setColumnsWidth(120, ['Dashboard!A:E']); + spreadsheet.setRowsHeight(40, ['budgetSheet!3', 'actuals!3', 'Variance!3', 'actuals!B3:I3', 'Dashboard!9', 'Dashboard!4', 'Dashboard!21', 'Dashboard!27']); + spreadsheet.setRowsHeight(25, ['budgetSheet!4:33', 'actuals!4:10000', 'actuals!B4:I33', 'Variance!4:33', 'Dashboard!5:8', 'Dashboard!10:20', 'Dashboard!22:24', 'Dashboard!28:37']); + setTimeout(() => { + budgetSheetCalculation(spreadsheet); + }, 100); + actualsSheetCalculation(spreadsheet); + varianceSheetCalculation(spreadsheet); + spreadsheet.cellFormat({ textAlign: 'center' }, 'Variance!C3:M100'); + spreadsheet.cellFormat({ textAlign: 'center' }, 'actuals!C3:L1000'); + spreadsheet.cellFormat({ textAlign: 'center' }, 'budgetSheet!A3:L33'); + spreadsheet.cellFormat({ backgroundColor: '#ffffcc' }, 'budgetSheet!B3:L3'); + spreadsheet.cellFormat({ backgroundColor: '#ffffcc' }, 'actuals!B3:L3'); + spreadsheet.cellFormat({ backgroundColor: '#ffffcc' }, 'Variance!B3:L3'); + setTimeout(() => { + dashboardCalculation(spreadsheet); + spreadsheet.cellFormat({ backgroundColor: '#ffffcc' }, 'Dashboard!A4:B4 D4:E4 A9:E9 A21:E21 A27:B27 D27:E27'); + spreadsheet.cellFormat({ backgroundColor: '#CDE5E7' }, 'Dashboard!B5:B6 B28:B37 D28:D30 E5:E7 B10:B19 B22:B24 D10:D19 D22:D24'); + spreadsheet.cellFormat({ backgroundColor: '#5FA4A9 ' }, 'Dashboard!A5:A6 A28:A37 D5:D7 E28:E30 A10:A19 A22:A24 C10:C19 C22:C24 E10:E19 E22:E24'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Dashboard!B5:B6 B28:B37 D28:D30 E5:E7 B10:B19 B22:B24 D10:D19 D22:D24', 'Vertical'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Dashboard!A5:A6 A28:A37 D5:D7 E28:E30 A10:A19 A22:A24 C10:C19 C22:C24 E10:E19 E22:E24', 'Vertical'); + }, 100); + } + + const budgetSheetCalculation = (spreadsheet) => { + spreadsheet.updateCell({ value:'Credit Card Expense Budget'},'budgetSheet!B1'); + spreadsheet.updateCell({ value: 'Expected Spend' }, `budgetSheet!J3`); + spreadsheet.updateCell({ value: 'Revolving Balance' }, `budgetSheet!K3`); + spreadsheet.updateCell({ value: 'Expected Interest' }, `budgetSheet!L3`); + spreadsheet.numberFormat('$#,##0.00', 'budgetSheet!G1:G33'); + spreadsheet.numberFormat('$#,##0.00', 'budgetSheet!J1:L33'); + spreadsheet.merge('budgetSheet!B1:L2'); + spreadsheet.cellFormat({ backgroundColor: '#CDE5E7' }, 'budgetSheet!C4:C33 E4:E33 G4:G33 I4:I33 K4:K33'); + spreadsheet.cellFormat({ fontWeight: 'bold', fontSize: '13pt', verticalAlign: 'middle', textAlign:'center' }, 'budgetSheet!B1:L2 B3:L3'); + const sheetModel = getSheet(spreadsheet, 1); + for (let i = 4; i < 34; i++) { + const regionCell = sheetModel.rows[i - 1].cells[1].value; + const branchesForRegion = regionBranches[regionCell]; + spreadsheet.addDataValidation( + { type: 'List', value1: branchesForRegion.join(','), ignoreBlank: false }, + `budgetSheet!C${i}` + ); + spreadsheet.updateCell({ formula: `=E${i}* F${i} * G${i}` }, `budgetSheet!J${i}`); + spreadsheet.updateCell({ formula: `=J${i}* H${i}` }, `budgetSheet!K${i}`); + spreadsheet.updateCell({ formula: `=K${i}* I${i}` }, `budgetSheet!L${i}`); + } + spreadsheet.addDataValidation({ type: 'List', value1: 'North,South,East,West', ignoreBlank: false }, 'budgetSheet!B4:B33'); + spreadsheet.protectSheet(1, { selectCells: true, selectUnLockedCells: true, formatCells: true, formatRows: true, formatColumns: true, insertLink: false }); + } + const interestRateMatrix = { + Chennai: { Platinum: 0.34, Gold: 0.32, Classic: 0.30 }, + Coimbatore:{ Platinum: 0.35, Gold: 0.32, Classic: 0.30 }, + Madurai: { Platinum: 0.34, Gold: 0.34, Classic: 0.31 }, + Trichy: { Platinum: 0.37, Gold: 0.33, Classic: 0.29 }, + Pune: { Platinum: 0.33, Gold: 0.31, Classic: 0.29 }, + Delhi: { Platinum: 0.36, Gold: 0.32, Classic: 0.28 }, + Kochi: { Platinum: 0.32, Gold: 0.30, Classic: 0.29 }, + Bengaluru: { Platinum: 0.38, Gold: 0.34, Classic: 0.31 }, + Kolkata: { Platinum: 0.35, Gold: 0.33, Classic: 0.29 }, + Mumbai: { Platinum: 0.37, Gold: 0.34, Classic: 0.30 } + }; + + const regionBranches = { + South: ['Chennai','Coimbatore','Madurai','Trichy','Kochi','Bengaluru'], + West: ['Pune','Mumbai'], + North: ['Delhi'], + East: ['Kolkata'] + }; + + const actualDataSource = () => { + const branches = ['Chennai', 'Coimbatore', 'Madurai', 'Trichy', 'Pune', + 'Delhi', 'Kochi', 'Bengaluru', 'Kolkata', 'Mumbai']; + const cardTypes = ['Platinum', 'Gold', 'Classic']; + const yesNo = ['Yes', 'No']; + const startDate = new Date(2025, 0, 1).getTime(); + const endDate = new Date(2025, 12, 31).getTime(); + const dateRange = endDate - startDate; + const actualsData = []; + for (let i = 0; i < 100; i++) { + const randomDate = new Date(startDate + Math.random() * dateRange); + const branch = branches[Math.floor(Math.random() * branches.length)]; + const cardType = cardTypes[Math.floor(Math.random() * cardTypes.length)]; + const cardId = `CC${String(Math.floor(Math.random() * 9000000) + 1000000)}`; + const maxOutstanding = 50000; + const outstandingBalance = Math.floor(Math.random() * (maxOutstanding + 1)); // can be 0 + const minimumPayment = +(outstandingBalance * 0.40).toFixed(2); + let transactionAmt = 0; + let revolvingFlag = 'No'; + let interestCharged = 0; + let minimumPaymentMet = 'No'; + let delinquencyFlag = 'No'; + if (outstandingBalance === 0) { + // no balance -> no transaction, no interest, no delinquency + transactionAmt = 0; + minimumPaymentMet = 'No'; + revolvingFlag = 'No'; + interestCharged = 0; + delinquencyFlag = 'No'; + } else { + const interestRate = getInterestRate(branch, cardType) || 0; + // 20% chance to pay full outstanding (remaining === 0) + if (Math.random() < 0.20) { + transactionAmt = outstandingBalance; // remaining = 0 + } else { + // ensure remaining > 0 by picking 1..outstandingBalance-1 when possible + if (outstandingBalance > 1) { + transactionAmt = Math.floor(Math.random() * (outstandingBalance - 1)) + 1; // 1 .. outstandingBalance-1 + } else { + transactionAmt = 1; // outstandingBalance == 1 -> pay 1 (remaining 0) but that case is rare + } + } + const remaining = outstandingBalance - transactionAmt; + minimumPaymentMet = (transactionAmt >= minimumPayment && transactionAmt > 0) ? 'Yes' : 'No'; + if (remaining === 0) { + revolvingFlag = 'No'; + interestCharged = 0; + } else { + revolvingFlag = 'Yes'; + interestCharged = parseFloat((remaining * interestRate).toFixed(2)); + } + delinquencyFlag = (outstandingBalance > 0 && minimumPaymentMet === 'No') ? 'Yes' : 'No'; + } + actualsData.push({ + 'Date': randomDate.toLocaleDateString('en-IN'), + 'Branch': branch, + 'Card Type': cardType, + 'Card ID': cardId, + 'Balance Due': outstandingBalance, + 'Minimum Due': minimumPayment, + 'Credit Amount': transactionAmt, + 'Paid Minimum': minimumPaymentMet, + 'Balance Carried': revolvingFlag, + 'Interest Amount': interestCharged, + 'Payment Due': delinquencyFlag + }); + } + return actualsData; + } + const getInterestRate = (branch, cardType) => { + const base = interestRateMatrix[branch]?.[cardType]; + return base; }; - const dataBound = () => { - //updating formula for budget sheet and perform auto-fill - spreadsheet.cellFormat({ fontWeight: 'bold'}, 'Variance!A7:A22'); - spreadsheet.updateCell({formula:`=SUM(Budget!B2:M2)`},'Budget!N2'); - spreadsheet.autoFill('Budget!N3:N13', 'Budget!N2', 'Down', 'FillWithoutFormatting'); - //updating formula for actual sheet and perform auto-fill - spreadsheet.updateCell({formula:`=SUM(Actual!B2:M2)`},'Actual!N2'); - spreadsheet.autoFill('Actual!N3:N13', 'Actual!N2', 'Down', 'FillWithoutFormatting'); - //variance calculation - spreadsheet.updateCell({formula:`=Variance!C7-Variance!B7`},'Variance!D7'); - spreadsheet.autoFill('Variance!D8:D18', 'Variance!D7', 'Down', 'FillSeries'); - //variance percentage - spreadsheet.updateCell({formula:`=Variance!D7/Variance!B7`},'Variance!E7'); - spreadsheet.autoFill('Variance!E8:E18', 'Variance!E7', 'Down', 'FillSeries'); - //Total variance and variance % - spreadsheet.updateCell({ formula: `=SUM(D7:D18)` }, 'Variance!D4'); - spreadsheet.updateCell({ formula: `=D4/A4` }, 'Variance!E4'); - //applying number format to variance % - spreadsheet.numberFormat('0.00%','Variance!E3:E22'); - // Budget Sheet Formatting - spreadsheet.cellFormat({backgroundColor: '#4472C4', color: '#FFFFFF', fontWeight: 'bold',textAlign:'center',verticalAlign:'middle',fontSize:'16pt'}, 'Budget!A1:N1'); - spreadsheet.cellFormat({backgroundColor: '#4472C4', color: '#FFFFFF', fontWeight: 'bold',textAlign:'center',verticalAlign:'middle',fontSize:'16pt'}, 'Actual!A1:N1'); - spreadsheet.cellFormat({backgroundColor: '#D9E1F2'}, 'Budget!A2:N2 A4:N4 A6:N6 A8:N8 A10:N10 A12:N12'); - spreadsheet.cellFormat({backgroundColor: '#D9E1F2'}, 'Actual!A2:N2 A4:N4 A6:N6 A8:N8 A10:N10 A12:N12'); - spreadsheet.cellFormat({backgroundColor: '#ffcccc'}, 'Actual!A3:N3 A5:N5 A7:N7 A9:N9 A11:N11 A13:N13'); - spreadsheet.cellFormat({backgroundColor: '#ffcccc'}, 'Budget!A3:N3 A5:N5 A7:N7 A9:N9 A11:N11 A13:N13'); - spreadsheet.cellFormat({backgroundColor: '#4472C4', color: '#FFFFFF', fontWeight: 'bold',}, 'Actual!A1:N1'); - //Variance Sheet Formatting - spreadsheet.merge('Variance!A1:E1'); - spreadsheet.cellFormat({ fontWeight: 'bold', backgroundColor: '#b3ffb3' }, 'Variance!A1:E1'); - spreadsheet.cellFormat({ color: 'black', fontSize: '23pt', fontWeight: 'bold', textAlign: 'center' }, 'Variance!A1:E1'); - spreadsheet.cellFormat({ verticalAlign: 'middle', textAlign: 'center' }, `Variance!A1:K20`); - spreadsheet.cellFormat({ fontWeight: 'bold', fontSize: '15pt' }, `Variance!A6:F6`); - spreadsheet.setBorder({ border: '1px solid black' }, 'Variance!A1:E1', 'Outer'); - spreadsheet.setBorder({ border: '1px solid black' }, 'Variance!A3:B4 D3:E4', 'Inner'); - spreadsheet.setBorder({ border: '1px solid black' }, 'Variance!A3:B4 D3:E4', 'Outer'); - spreadsheet.setBorder({ border: '1px solid black' }, 'Variance!A6:E19', 'Vertical'); - spreadsheet.setBorder({ borderBottom: '1px solid black' }, 'Variance!A6:E19', 'Horizontal'); - spreadsheet.setBorder({ border: '1px solid black' }, 'Variance!A6:E6', 'Horizontal'); - spreadsheet.cellFormat({ backgroundColor: '#ccccff',fontWeight:'bold',fontSize:'14pt'}, 'Variance!A3:B4 D3:E4'); - //conditional formatting for variance and variance % column - spreadsheet.conditionalFormat({ type: 'ThreeSymbols', range: `Variance!E6:E22` }); - spreadsheet.conditionalFormat({ type: 'ThreeTriangles', range: `Variance!D6:D22` }); - //number formattings - spreadsheet.numberFormat('$#,##0.00','Variance!A4:D4 C7:D22'); - spreadsheet.numberFormat('$#,##0.00','Budget!B2:N13'); - spreadsheet.numberFormat('$#,##0.00','Actual!B2:N13'); - //setting row height to budget and actual sheet - spreadsheet.setRowsHeight(40, ['Budget!1', 'Actual!1'],true); - spreadsheet.setRowsHeight(30, ['Budget!2:22', 'Actual!2:22'],true); + const actualsSheetCalculation = (spreadsheet) => { + spreadsheet.updateCell({ value:'Credit Card Expense Summary'},'actuals!B1'); + spreadsheet.merge('actuals!B1:L2'); + spreadsheet.cellFormat({ fontWeight: 'bold', fontSize: '13pt', verticalAlign: 'middle', textAlign: 'center' }, 'actuals!B1:L2 B3:L3'); + spreadsheet.cellFormat({ textAlign: 'left' }, 'actuals!B4:B1000'); + spreadsheet.numberFormat('$#,##0.00', 'actuals!F1:H1000'); + spreadsheet.numberFormat('$#,##0.00', 'actuals!K1:K1000'); + spreadsheet.updateRange({ dataSource: actualDataSource(), startCell: 'actuals!B3' }, 2); + spreadsheet.addDataValidation({ type: 'List', value1: 'Yes,No', ignoreBlank: false }, 'actuals!I4:J1000'); + spreadsheet.addDataValidation({ type: 'List', value1: 'Yes,No', ignoreBlank: false }, 'actuals!L4:L1000'); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'Yes', range: 'actuals!H4:H1000', cFColor: 'RedT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'No', range: 'actuals!H4:H1000', format: { style: { color: 'Green' } } }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'Yes', range: 'actuals!J4:J1000', cFColor: 'RedFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'No', range: 'actuals!J4:J1000', cFColor: 'GreenFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'No', range: 'actuals!I4:I1000', cFColor: 'RedFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'Yes', range: 'actuals!I4:I1000', cFColor: 'GreenFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'No', range: 'actuals!I4:I1000', cFColor: 'RedFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'Yes', range: 'actuals!I4:I1000', cFColor: 'GreenFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'Yes', range: 'actuals!L4:L1000', cFColor: 'RedFT' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', value: 'No', range: 'actuals!L4:L1000', cFColor: 'GreenFT' }); + spreadsheet.protectSheet(2, { selectCells: true, selectUnLockedCells: true, formatCells: true, formatRows: true, formatColumns: true, insertLink: false }); }; - const pieChart = [{ type: 'Pie', range: 'Variance!D7:D18', title: 'VARIANCE', theme: 'Bootstrap5', height: 290, width: 720, top: 300, left: 773, id: 'Chart2', isSeriesInRows: false, legendSettings: { visible: false } }]; - const columnChart = [{ type: 'Column', range: 'Variance!A6:C18', title: 'PLANNED BUDGET VS ACTUAL SPENT', theme: 'Bootstrap5',height: 290, width: 720, top: 2, left: 773, id: 'Chart1', isSeriesInRows: true }]; - return (<> -
- - -
- { spreadsheet = ssObj }} dataBound={dataBound}> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) + + const varianceSheetCalculation = (spreadsheet) => { + spreadsheet.updateCell({ value:'Credit Card Expense Variance Analysis'},'Variance!B1'); + spreadsheet.merge('Variance!B1:L2'); + spreadsheet.cellFormat({ fontWeight: 'bold', fontSize: '13pt', verticalAlign: 'middle', textAlign:'center' }, 'Variance!B1:L2 B3:M3'); + const headers = ['Branch', 'Card Type', 'Expected Spend', 'Actual Spend', 'Variance', 'Variance %', 'Expected Interest', 'Actual Interest', 'Payment Risk %', 'Risk Score', 'Risk Level']; //'Run_Rate', + const locations = ['Bengaluru', 'Chennai', 'Coimbatore', 'Delhi', 'Kochi', 'Kolkata', 'Madurai', 'Mumbai', 'Pune', 'Trichy']; + headers.forEach((val, i) => { + const col = String.fromCharCode(66 + i); + spreadsheet.updateCell({ value: val }, `variance!${col}3`); + }); + const cardTypes = ['Gold', 'Classic', 'Platinum']; + let row = 4; + locations.forEach((loc) => { + cardTypes.forEach((cardVal) => { + spreadsheet.updateCell({ value: loc }, `variance!B${row}`); + spreadsheet.updateCell({ value: cardVal }, `variance!C${row}`); + row++; + }); + }); + let i = 4; + for (let i = 4; i < row; i++) { + spreadsheet.updateCell({ formula: `=SUMIFS(budgetSheet!J4:J33, budgetSheet!C4:C33, Variance!B${i}, budgetSheet!D4:D33, Variance!C${i})` }, `Variance!D${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!G4:G1000, actuals!C4:C1000, Variance!B${i}, actuals!D4:D1000, Variance!C${i})` }, `Variance!E${i}`); + spreadsheet.updateCell({ formula: `=Variance!D${i} - Variance!E${i}` }, `Variance!F${i}`); + spreadsheet.updateCell({ formula: `=Variance!F${i} / Variance!D${i}` }, `Variance!G${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(budgetSheet!L4:L33, budgetSheet!C4:C33, Variance!B${i}, budgetSheet!D4:D33, Variance!C${i})` }, `Variance!H${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!K4:K1000, actuals!C4:C1000, Variance!B${i}, actuals!D4:D1000, Variance!C${i})` }, `Variance!I${i}`); + spreadsheet.updateCell({ formula: `=SUMIFS(actuals!H4:H1000,actuals!C4:C1000,Variance!B${i}, actuals!D4:D1000 , Variance!C${i},actuals!L4:L1000,"Yes")/SUMIFS(actuals!H4:H1000,actuals!C4:C1000,Variance!B${i}, actuals!D4:D1000 , Variance!C${i})` }, `Variance!J${i}`); + spreadsheet.updateCell({ formula: `=(budgetSheet!H${i}*0.4)+(Variance!J${i}*0.6)` }, `Variance!K${i}`); + spreadsheet.updateCell({ formula: `=IF(Variance!K${i}>0.30,"High Risk",IF(Variance!K${i}>0.20,"Moderate Risk","Low Risk"))` }, `Variance!L${i}`); + } + spreadsheet.numberFormat('$#,##0.00', 'Variance!D4:F33'); + spreadsheet.numberFormat('$#,##0.00', 'Variance!H4:I33'); + spreadsheet.numberFormat('0.00%', 'Variance!K4:K33'); + spreadsheet.numberFormat('0.00%', 'Variance!G4:G33'); + spreadsheet.numberFormat('0.00%', 'Variance!J4:J33'); + spreadsheet.conditionalFormat({ type: 'FiveQuarters', range: 'Variance!J4:J33' }); + spreadsheet.conditionalFormat({ type: 'ThreeArrows', range: 'Variance!L4:L33' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', cFColor: 'GreenFT', value: 'Low Risk', range: 'Variance!L4:L33' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', cFColor: 'YellowFT', value: 'Moderate Risk', range: 'Variance!L4:L33' }); + spreadsheet.conditionalFormat({ type: 'EqualTo', cFColor: 'RedFT', value: 'High Risk', range: 'Variance!L4:L33' }); + spreadsheet.protectSheet(3, { selectCells: true, selectUnLockedCells: true, formatCells: true, formatRows: true, formatColumns: true, insertLink: false }); + }; + + const dashboardCalculation = (spreadsheet) => { + spreadsheet.cellFormat({ fontWeight: 'bold', fontSize: '13pt', verticalAlign: 'middle', textAlign: 'center' }, 'Dashboard!A2:E2 A4:E4 A9:E9 A21:E21 A27:E27'); + const metrics = ['Total Spend', 'Total Interest']; + const locations = ['Bengaluru', 'Chennai', 'Coimbatore', 'Delhi', 'Kochi', 'Kolkata', 'Madurai', 'Mumbai', 'Pune', 'Trichy']; + const cardTypes = ['Gold', 'Classic', 'Platinum']; + let i = 5; + metrics.forEach((val) => { + spreadsheet.updateCell({ value: val }, `Dashboard!A${i}`); + i++; + }); + spreadsheet.merge('Dashboard!A4:B4'); + spreadsheet.merge('Dashboard!D4:E4'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'BudgetSheet!B3:L3'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Actuals!B3:L3'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Variance!B3:L3'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'BudgetSheet!B3:L33', 'Vertical'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Actuals!B3:L1000', 'Vertical'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Variance!B3:L33', 'Vertical'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Dashboard!A4:B4 D4:E4 A9:E9 A21:E21 A27:B27 D27:E27', 'Outer'); + spreadsheet.setBorder({ border: '1px solid #000000' }, 'Dashboard!A4:B4 D4:E4 A9:E9 A21:E21 A27:B27 D27:E27', 'Vertical'); + spreadsheet.updateCell({ formula: '=SUM(Variance!E4:E33)' }, 'Dashboard!B5'); + spreadsheet.updateCell({ formula: '=SUM(Variance!I4:I33)' }, 'Dashboard!B6'); + const branchSpend = ['Branch', 'Actual Spend', 'Actual Interest', 'Variance', 'Planned Spend']; + const cardSpend = ['Card Type', 'Actual Spend', 'Actual Interest', 'Variance', 'Planned Spend']; + const cardRisk = ['Low Risk', 'Moderate Risk', 'High Risk']; + const deliquentCalc = ['Branch', 'Payment Risk']; + const deliquentCalcCard = ['Card', 'Payment Risk']; + branchSpend.forEach((val, i) => { + const col = String.fromCharCode(65 + i); + spreadsheet.updateCell({ value: val }, `Dashboard!${col}9`); + }); + cardSpend.forEach((val, i) => { + const col = String.fromCharCode(65 + i); + spreadsheet.updateCell({ value: val }, `Dashboard!${col}21`); + }); + let j = 10; + let newLocation = 28; + locations.forEach((val) => { + spreadsheet.updateCell({ value: val }, `Dashboard!A${j}`); + spreadsheet.updateCell({ value: val }, `Dashboard!A${newLocation}`); + spreadsheet.updateCell({ formula: `=AVERAGEIF(Variance!B4:B33,A${newLocation},Variance!J4:J33)` }, `Dashboard!B${newLocation}`); + newLocation++; + j++; + }); + for (let k = 10; k < 20; k++) { + spreadsheet.updateCell({ formula: `=SUMIF(Variance!B4:B33,Dashboard!A${k},Variance!E4:E33` }, `Dashboard!B${k}`); + spreadsheet.updateCell({ formula: `=SUMIF(Variance!B4:B33,Dashboard!A${k},Variance!I4:I33` }, `Dashboard!C${k}`); + spreadsheet.updateCell({ formula: `=SUMIF(Variance!B4:B33,Dashboard!A${k},Variance!F4:F33` }, `Dashboard!D${k}`); + spreadsheet.updateCell({ formula: `=SUMIF(budgetSheet!C4:C33,Dashboard!A${k},budgetSheet!J4:J33` }, `Dashboard!E${k}`); + } + let cardTrackNumber = 22; + cardTypes.forEach((val) => { + spreadsheet.updateCell({ value: val }, `Dashboard!A${cardTrackNumber}`); + spreadsheet.updateCell({ value: val }, `Dashboard!D${cardTrackNumber + 6}`); + spreadsheet.updateCell({ formula: `=AVERAGEIF(Variance!C4:C33,D${cardTrackNumber + 6} , Variance!J4:J33)` }, `Dashboard!E${cardTrackNumber + 6}`); + cardTrackNumber++; + }) + for (let i = 22; i < 25; i++) { + spreadsheet.updateCell({ formula: `=SUMIF(Variance!C4:C33,Dashboard!A${i},Variance!E4:E33` }, `Dashboard!B${i}`); + spreadsheet.updateCell({ formula: `=SUMIF(Variance!C4:C33,Dashboard!A${i},Variance!I4:I33` }, `Dashboard!C${i}`); + spreadsheet.updateCell({ formula: `=SUMIF(Variance!C4:C33,Dashboard!A${i},Variance!F4:F33` }, `Dashboard!D${i}`); + spreadsheet.updateCell({ formula: `=SUMIF(budgetSheet!D4:D33,Dashboard!A${i},budgetSheet!J4:J33` }, `Dashboard!E${i}`); + } + deliquentCalc.forEach((val, i) => { + const col = String.fromCharCode(65 + i); + spreadsheet.updateCell({ value: val }, `Dashboard!${col}27`); + }) + deliquentCalcCard.forEach((val, i) => { + const col = String.fromCharCode(68 + i); + spreadsheet.updateCell({ value: val }, `Dashboard!${col}27`); + }) + spreadsheet.updateCell({ value: 'Key Metrics' }, 'Dashboard!A4'); + spreadsheet.updateCell({ value: 'Credit Card Risk State' }, 'Dashboard!D4'); + let cardRiskNumber = 5; + cardRisk.forEach((val) => { + spreadsheet.updateCell({ value: val }, `Dashboard!D${cardRiskNumber}`); + spreadsheet.updateCell({ formula: `=COUNTIF(Variance!L4:L33,Dashboard!D${cardRiskNumber})` }, `Dashboard!E${cardRiskNumber}`); + cardRiskNumber++; + }); + spreadsheet.numberFormat('$#,##0.00', 'Dashboard!B10:E24'); + spreadsheet.numberFormat('$#,##0.00', 'Dashboard!B4:B6'); + spreadsheet.numberFormat('0.00%', 'Dashboard!B28:B37'); + spreadsheet.numberFormat('0.00%', 'Dashboard!E28:E30'); + spreadsheet.insertChart(chart1); + spreadsheet.insertChart(chart2); + spreadsheet.insertChart(chart3); + spreadsheet.insertChart(chart4); + spreadsheet.insertChart(chart5); + spreadsheet.insertChart(chart6); + spreadsheet.protectSheet(0, { selectCells: true, selectUnLockedCells: true, formatCells: true, formatRows: true, formatColumns: true, insertLink: false }); + } + const chart1 = [{ type: 'Column', range: 'Dashboard!A9:C19', title: 'BRANCH WISE SUMMARY', theme: 'Bootstrap5', left: 602, top: 282, width: 1194, height: 416, id: 'Chart1', isSeriesInRows: false, legendSettings: { visible: false } }]; + const chart2 = [{ type: 'StackingLine', range: 'Dashboard!A21:C24', title: 'CARD TYPE SUMMARY', theme: 'Bootstrap5', height: 280, left: 602, top: 701, width: 585, id: 'Chart2', isSeriesInRows: true }]; + const chart3 = [{ type: 'Doughnut', range: 'Dashboard!A5:B6', title: 'TOTAL SPEND VS TOTAL INTEREST', theme: 'Bootstrap5', height: 280, left: 608, top: 0, width: 365, id: 'Chart3' }]; + const chart4 = [{ type: 'Pie', range: 'Dashboard!A27:B37', title: 'PAYMENT RISK BASED ON LOCATION', theme: 'Bootstrap5', height: 279, left: 1407, width: 507, top: 0, id: 'Chart4' }]; + const chart5 = [{ type: 'Area', range: 'Dashboard!D27:E30', title: 'PAYMENT RISK BASED ON CARD', theme: 'Bootstrap5', top: 0, width: 430, left: 976, height: 280, id: 'Chart5' }]; + const chart6 = [{ type: 'Bar', range: 'Dashboard!D5:E7', title: 'RISK INSIGHTS OF CREDIT CARD', theme: 'Bootstrap5', height: 280, left: 1189, top: 701, width: 585, id: 'Chart6' }]; + return ( + { spreadsheet = ssObj }} created={onCreated.bind(this)} cellSave={onCellSave} actionComplete={actionComplete} actionBegin={actionBegin} + openUrl='https://document.syncfusion.com/web-services/spreadsheet-editor/api/spreadsheet/open' + saveUrl='https://document.syncfusion.com/web-services/spreadsheet-editor/api/spreadsheet/save' + > + + + + + + + + ); } \ No newline at end of file diff --git a/src/index.css b/src/index.css index c5f656f..e69de29 100644 --- a/src/index.css +++ b/src/index.css @@ -1,10 +0,0 @@ -@import '../node_modules/@syncfusion/ej2-base/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-lists/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-popups/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-grids/styles/material.css'; -@import '../node_modules/@syncfusion/ej2-react-spreadsheet/styles/material.css'; \ No newline at end of file