// kajla tankolási napló – új, üres Google-táblázatban futtasd. function setupTemplate() { const book = SpreadsheetApp.getActiveSpreadsheet(); if (!book) throw new Error('Nyiss egy új Google-táblázatot, majd annak Bővítmények → Apps Script menüjét.'); const active = Session.getActiveUser().getEmail().toLowerCase(); const effective = Session.getEffectiveUser().getEmail().toLowerCase(); if (!active || active !== effective) throw new Error('A saját Google-fiókodból futtasd.'); const props = PropertiesService.getScriptProperties(); if (props.getProperty('OWNER_EMAIL') && props.getProperty('OWNER_EMAIL') !== active) throw new Error('Másik tulajdonos van beállítva.'); if (props.getProperty('BOOK_ID')) { if (props.getProperty('BOOK_ID') !== book.getId()) throw new Error('Ez a program már másik táblázathoz tartozik.'); initialize(); return 'A napló már elkészült. A meglévő adatok nem változtak.'; } const names = ['Tankolások','Éves bontás','Dashboard','Szervizek','Listák']; if (names.some(name => book.getSheetByName(name))) throw new Error('Már létezik egy naplólap. A sablont új, üres táblázatban állítsd be; meglévő lapot nem ír felül.'); if (book.getSheets().some(sheet => sheet.getLastRow() > 0)) throw new Error('A táblázat nem üres. Hozz létre új, üres táblázatot.'); book.setSpreadsheetLocale('hu_HU').setSpreadsheetTimeZone(ZONE); const sheets = {}; names.forEach(name => sheets[name] = book.insertSheet(name)); const fuel = sheets['Tankolások'], annual = sheets['Éves bontás'], dash = sheets['Dashboard'], lists = sheets['Listák']; fuel.insertRowsAfter(fuel.getMaxRows(), 2001 - fuel.getMaxRows()); const headers = ['Dátum','Idő','Márka','Hely','Egységár','Teljes költség','Mennyiség','Kilométer óra','Megtett út','Átlagfogyasztás','Üzemanyag típus','Pénznem','Tele tank?','Megjegyzés']; styleTable_(fuel, headers, 2001); fuel.setFrozenColumns(4); fuel.getRange('A2:A2001').setNumberFormat('yyyy.mm.dd.'); fuel.getRange('B2:B2001').setNumberFormat('hh:mm'); fuel.getRange('E2:E2001').setNumberFormat('#,##0.00" Ft/l"'); fuel.getRange('F2:F2001').setNumberFormat('#,##0" Ft"'); fuel.getRange('G2:G2001').setNumberFormat('#,##0.00" l"'); fuel.getRange('H2:I2001').setNumberFormat('#,##0" km"'); fuel.getRange('J2:J2001').setNumberFormat('0.00" l/100 km"'); fuel.getRange('M2:M2001').insertCheckboxes().setValue(true); fuel.getRange('M1').setNote('Az űrlapon: Teletankoltam. Részleges tankolásnál kapcsold ki.'); fuel.getRange('J1').setNote('Az előző teletankolás óta tankolt összes liter / megtett út × 100. Az első teletankolásnál és részleges tankoláskor üres.'); fuel.getRange('G2:G2001').setBackground('#edf4ef'); fuel.getRange('I2:J2001').setBackground('#edf4ef'); styleTable_(lists, ['Márka','Hely'], 200); lists.getRange('A2:A4').setValues([['MOL'],['OMV'],['Shell']]); for (const [column, range] of [[3,'A2:A200'],[4,'B2:B200']]) fuel.getRange(2,column,2000,1).setDataValidation(SpreadsheetApp.newDataValidation().requireValueInRange(lists.getRange(range),true).setAllowInvalid(false).build()); fuel.getRange('K2:K2001').setDataValidation(SpreadsheetApp.newDataValidation().requireValueInList(['Prémium 95','100-as benzin','Dízel','Prémium dízel'],true).setAllowInvalid(false).build()); fuel.getRange('L2:L2001').setDataValidation(SpreadsheetApp.newDataValidation().requireValueInList(['HUF','EUR'],true).setAllowInvalid(false).build()); fuel.getRange('A1:N2001').createFilter(); fuel.setColumnWidth(4,180).setColumnWidth(14,280); setupAnnual_(annual); styleTable_(dash,['Mutató','Érték'],8); dash.getRange('A2:A7').setValues([['Tankolások száma'],['Megtett út'],['Tankolt mennyiség'],['Költség (HUF)'],['Költség (EUR)'],['Leghosszabb táv két tankolás között']]); dash.getRange('B2:B7').setFormulas([ ['=SUM(\'Éves bontás\'!B2:B201)'],['=SUM(\'Éves bontás\'!C2:C201)'],['=SUM(\'Éves bontás\'!D2:D201)'],['=SUM(\'Éves bontás\'!E2:E201)'],['=SUM(\'Éves bontás\'!F2:F201)'],['=IF(COUNT(\'Éves bontás\'!M2:M201)=0,"",MAX(\'Éves bontás\'!M2:M201))'] ]); dash.getRange('A8').setValue('Leghosszabb táv dátuma (záró tankolás)'); dash.getRange('B8').setFormula('=IF(B7="","",INDEX(\'Éves bontás\'!N2:N201,MATCH(B7,\'Éves bontás\'!M2:M201,0)))').setNumberFormat('yyyy.mm.dd.'); dash.getRange('B3').setNumberFormat('#,##0" km"'); dash.getRange('B4').setNumberFormat('#,##0.00" l"'); dash.getRange('B5').setNumberFormat('#,##0" Ft"'); dash.getRange('B6').setNumberFormat('#,##0.00" €"'); dash.getRange('B7').setNumberFormat('#,##0" km"'); dash.setColumnWidth(1,350).setColumnWidth(2,190); const services = sheets['Szervizek']; styleTable_(services,['Dátum','Km-óraállás','Munka / alkatrész','Költség (Ft)','Megjegyzés'],501); services.getRange('A2:A501').setNumberFormat('yyyy.mm.dd.'); services.getRange('B2:B501').setNumberFormat('#,##0" km"'); services.getRange('D2:D501').setNumberFormat('#,##0" Ft"'); services.setColumnWidth(3,260).setColumnWidth(5,300); lists.hideSheet(); book.setActiveSheet(fuel); props.setProperty('BOOK_ID',book.getId()); initialize(); SpreadsheetApp.flush(); return 'Elkészült az üres napló. Bevezetés → Új bevezetés → Internetes alkalmazás. Végrehajtás: Én; hozzáférés: Csak nekem.'; } function styleTable_(sheet, headers, rows) { sheet.getRange(1,1,rows,headers.length).setFontFamily('Arial').setFontSize(10); sheet.getRange(1,1,1,headers.length).setValues([headers]); sheet.getRange(1,1,rows,headers.length).applyRowBanding(SpreadsheetApp.BandingTheme.LIGHT_GREY); sheet.getRange(1,1,1,headers.length).setBackground('#173d48').setFontColor('#ffffff').setFontWeight('bold').setWrap(true); sheet.setFrozenRows(1).setRowHeight(1,44).setColumnWidths(1,headers.length,145); } function setupAnnual_(sheet) { const headers=['Év','Tankolások','Megtett út','Tankolt mennyiség','Költség (HUF)','Költség (EUR)','Mért átlagfogyasztás','Mérések száma','Min. literár (HUF)','Max. literár (HUF)','Min. literár (EUR)','Max. literár (EUR)','Leghosszabb táv','Dátuma']; styleTable_(sheet,headers,201); const col=letter=>"'Tankolások'!"+letter+'$2:'+letter+'$2001'; const dates=col('A'); sheet.getRange('A2').setFormula('=IF(COUNT('+dates+')=0,YEAR(TODAY()),YEAR(MIN('+dates+')))'); sheet.getRange('A3:A201').setFormulas(Array.from({length:199},(_,i)=>{const r=i+3;return ['=IF(A'+(r-1)+'="","",IF(A'+(r-1)+'{ const r=i+2, year='A'+r, start='DATE('+year+',1,1)', end='DATE('+year+'+1,1,1)'; const criteria=dates+',">="&'+start+','+dates+',"<"&'+end; const filter=dates+'>='+start+','+dates+'<'+end; const price=currency=>col('L')+'="'+currency+'"'; const stat=(fn,currency)=>'IFERROR('+fn+'(FILTER('+col('E')+','+filter+','+price(currency)+','+col('E')+'>0)),"")'; const expr=[ 'COUNTIFS('+criteria+')', 'SUMIFS('+col('I')+','+criteria+')', 'SUMIFS('+col('G')+','+criteria+')', 'SUMIFS('+col('F')+','+criteria+','+col('L')+',"HUF")', 'SUMIFS('+col('F')+','+criteria+','+col('L')+',"EUR")', 'IFERROR(AVERAGE(FILTER('+col('J')+','+filter+','+col('J')+'>0)),"")', 'COUNTIFS('+criteria+','+col('J')+',">0")', stat('MIN','HUF'),stat('MAX','HUF'),stat('MIN','EUR'),stat('MAX','EUR'), 'IFERROR(MAX(FILTER('+col('I')+','+filter+','+col('I')+'>0)),"")', 'IF(M'+r+'="","",IFERROR(INDEX(FILTER('+dates+','+filter+','+col('I')+'=M'+r+'),1),""))' ]; return expr.map(e=>'=IF('+year+'="","",'+e+')'); }); sheet.getRange('B2:N201').setFormulas(formulas); sheet.getRange('C2:C201').setNumberFormat('#,##0" km"'); sheet.getRange('D2:D201').setNumberFormat('#,##0.00" l"'); sheet.getRange('E2:E201').setNumberFormat('#,##0" Ft"'); sheet.getRange('F2:F201').setNumberFormat('#,##0.00" €"'); sheet.getRange('G2:G201').setNumberFormat('0.00" l/100 km"'); sheet.getRange('I2:J201').setNumberFormat('#,##0.00" Ft/l"'); sheet.getRange('K2:L201').setNumberFormat('0.000" €/l"'); sheet.getRange('M2:M201').setNumberFormat('#,##0" km"'); sheet.getRange('N2:N201').setNumberFormat('yyyy.mm.dd.'); sheet.getRange('G1').setNote('A tankoláskor mért fogyasztások egyszerű átlaga. Csak befejezett teletankolási szakaszok; nem éves liter/km hányados.'); sheet.getRange('N1').setNote('A szakaszt lezáró tankolás dátuma. Holtversenynél az első előfordulás.'); const chart=(title,type,ranges,row,colors)=>{ let b=sheet.newChart().setChartType(type).setPosition(row,16,0,0).setOption('title',title).setOption('width',640).setOption('height',300).setOption('colors',colors).setOption('backgroundColor','#ffffff').setNumHeaders(1); ranges.forEach(range=>b=b.addRange(sheet.getRange(range))); sheet.insertChart(b.build()); }; chart('Éves költség • HUF',Charts.ChartType.COLUMN,['A1:A201','E1:E201'],2,['#237a61']); chart('Literár • minimum és maximum (Ft/l)',Charts.ChartType.LINE,['A1:A201','I1:J201'],19,['#2447ed','#ff742f']); chart('Mért átlagfogyasztás (l/100 km)',Charts.ChartType.LINE,['A1:A201','G1:G201'],36,['#237a61']); }