src/app/services/spreadsheet.service.ts
| providedIn | root |
Properties |
|
Methods |
|
constructor(excelPasswordModalService: ExcelPasswordModalService, eventService: EventService, licenceService: LicenceService)
|
||||||||||||
|
Defined in src/app/services/spreadsheet.service.ts:16
|
||||||||||||
|
Parameters :
|
| Public bytesToMB | ||||||
bytesToMB(size: number)
|
||||||
|
Defined in src/app/services/spreadsheet.service.ts:171
|
||||||
|
Parameters :
Returns :
number
|
| Public parseExcelFile | ||||||||||||
parseExcelFile(parseParams: ParseParams, onParseStateChange?: (uploadState?: string) => void, onTableFoundEvent?: (info?: string) => void)
|
||||||||||||
|
Defined in src/app/services/spreadsheet.service.ts:24
|
||||||||||||
|
Parameters :
Returns :
Promise<ParseResult | undefined>
|
| Public Async parseExcelSheetNames | ||||||
parseExcelSheetNames(file: File)
|
||||||
|
Defined in src/app/services/spreadsheet.service.ts:78
|
||||||
|
Read the file minimally just to get the sheet names, not reading full file to help boost the performance
Parameters :
Returns :
Promise<{ sheetNames: string[]; password?: string }>
sheet names in string array |
| Public xlsxReadFile | ||||||||
xlsxReadFile(file: any)
|
||||||||
|
Defined in src/app/services/spreadsheet.service.ts:49
|
||||||||
|
Reads the excel file using the XLSX.read() function If possible, function will use the web worker to read it in background thread otherwise fallback method will be used
Parameters :
Returns :
Promise<XLSX.WorkBook>
WorkBook |
| Private licenceState |
Type : unknown
|
Default value : this.licenceService.licenceState
|
|
Defined in src/app/services/spreadsheet.service.ts:16
|
| Private promptExcelPassword |
Type : unknown
|
Default value : () => {...}
|
|
Defined in src/app/services/spreadsheet.service.ts:179
|
|
When excel is password protected we will display the password prompt for user to type password in. |
import { Injectable } from '@angular/core'
import { ExcelPasswordModalService } from '../shared/excel-password-modal/excel-password-modal.service'
import { EventService } from './event.service'
import { LicenceService } from './licence.service'
import { SpreadsheetUtil } from '../shared/spreadsheet-util/spreadsheet-util'
import { ParseParams } from '../models/ParseParams.interface'
import { ParseResult } from '../models/ParseResult.interface'
import { OpenOptions } from '../shared/excel-password-modal/models/options.interface'
import { Result } from '../shared/excel-password-modal/models/result.interface'
import * as XLSX from '@sheet/crypto'
@Injectable({
providedIn: 'root'
})
export class SpreadsheetService {
private licenceState = this.licenceService.licenceState
constructor(
private excelPasswordModalService: ExcelPasswordModalService,
private eventService: EventService,
private licenceService: LicenceService
) {}
public parseExcelFile(
parseParams: ParseParams,
onParseStateChange?: (uploadState: string) => void,
onTableFoundEvent?: (info: string) => void
): Promise<ParseResult | undefined> {
const spreadSheetUtil = new SpreadsheetUtil({
licenceState: this.licenceState
})
return spreadSheetUtil.parseSpreadsheetFile(
parseParams,
this.promptExcelPassword,
onParseStateChange,
onTableFoundEvent
)
}
/**
* Reads the excel file using the XLSX.read() function
* If possible, function will use the web worker to read it in background thread
* otherwise fallback method will be used
*
* @param file selected in an <input>
* @returns WorkBook
*/
public xlsxReadFile(file: any): Promise<XLSX.WorkBook> {
return new Promise((resolve, reject) => {
const spreadSheetUtil = new SpreadsheetUtil({
licenceState: this.licenceState
})
let reader: FileReader = new FileReader()
reader.onload = (fileReaderResponse: any) => {
spreadSheetUtil
.xslxStartReading(fileReaderResponse, this.promptExcelPassword)
.then((response) => {
resolve(response)
})
.catch((err) => {
reject(err)
})
}
reader.readAsArrayBuffer(file)
})
}
/**
* Read the file minimally just to get the sheet names, not reading full file
* to help boost the performance
*
* @returns sheet names in string array
*/
public async parseExcelSheetNames(file: File): Promise<{
sheetNames: string[]
password?: string
}> {
return new Promise((resolve, reject) => {
const reader = new FileReader()
if (!file) {
console.warn('file is missing')
return resolve({ sheetNames: [] })
}
reader.onload = async (event: ProgressEvent<FileReader>) => {
if (!event?.target) {
console.warn('File reader event.target is missing')
return
}
let wb: XLSX.WorkBook | undefined = undefined
let fileUnlocking: boolean = false
let password: string | undefined
const data = event.target.result
try {
wb = XLSX.read(data, {
// Load file minimally to parse sheets
bookSheets: true,
type: 'binary'
})
} catch (err: any) {
if (err.message.toLowerCase().includes('password')) {
fileUnlocking = true
let passwordError = false
while (fileUnlocking) {
password = await this.promptExcelPassword({
error: passwordError
})
if (password) {
try {
wb = XLSX.read(data, {
// Load file minimally to parse sheets
bookSheets: true,
type: 'binary',
password: password
})
fileUnlocking = false
passwordError = false
} catch (err: any) {
passwordError = true
if (!err.message.toLowerCase().includes('password')) {
fileUnlocking = false
}
}
if (!password)
return reject('Invalid password, failed to decrypt the file')
} else {
fileUnlocking = false
return reject('No password provided')
}
}
} else {
return reject('Error reading the file')
}
}
if (!wb) return reject('Error parsing the workbook')
try {
const sheetNames = wb.SheetNames
return resolve({
sheetNames: sheetNames,
password: password
})
} catch (e) {
console.error(e)
}
}
reader.onerror = function (ex) {
console.log(ex)
}
reader.readAsBinaryString(file)
})
}
public bytesToMB(size: number): number {
return parseFloat((size / (1024 * 1024)).toFixed(2))
}
/**
* When excel is password protected we will display the password prompt for user to type password in.
* @returns Password user input or undefined if discarded by user
*/
private promptExcelPassword = (
options?: OpenOptions
): Promise<string | undefined> => {
return new Promise((resolve, reject) => {
this.excelPasswordModalService
.open(options)
.subscribe((result: Result) => {
resolve(result.password)
})
})
}
}