[import] use xlsx-populate for password protected excel file

This commit is contained in:
Anantha Kumaran 2024-01-24 20:16:53 +05:30
parent d6f9ec368f
commit 544d6962e2
6 changed files with 3166 additions and 32 deletions

964
flake/node-package.nix generated

File diff suppressed because it is too large Load Diff

2167
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,8 @@
"svelte-tiny-virtual-list": "^2.0.5",
"textures": "^1.2.3",
"tippy.js": "^6.3.7",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz"
"xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz",
"xlsx-populate": "^1.21.0"
},
"devDependencies": {
"@codemirror/merge": "^6.1.1",
@ -104,6 +105,7 @@
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^5.0.0",
"vite-plugin-node-polyfills": "^0.19.0",
"wait-port": "^1.1.0"
},
"type": "module"

4
src/app.d.ts vendored
View File

@ -71,6 +71,10 @@ declare module "textures" {
export default textures;
}
declare module "xlsx-populate" {
export function fromDataAsync(data: ArrayBuffer, options: { password?: string }): any;
}
declare module "arima/async" {
export class Arima {
constructor(options: object);

View File

@ -3,6 +3,7 @@ import * as XLSX from "xlsx";
import _ from "lodash";
import { format } from "./journal";
import { pdf2array } from "./pdf";
import * as XlsxPopulate from "xlsx-populate";
interface Result {
data: string[][];
@ -75,13 +76,47 @@ function parseCSV(file: File): Promise<Result> {
async function parseXLSX(file: File): Promise<Result> {
const buffer = await readFile(file);
const sheet = XLSX.read(buffer, { type: "binary" });
const json = XLSX.utils.sheet_to_json<string[]>(sheet.Sheets[sheet.SheetNames[0]], {
header: 1,
blankrows: false,
rawNumbers: false
});
return { data: json };
try {
const sheet = XLSX.read(buffer, { type: "binary" });
const json = XLSX.utils.sheet_to_json<string[]>(sheet.Sheets[sheet.SheetNames[0]], {
header: 1,
blankrows: false,
rawNumbers: false
});
return { data: json };
} catch (e) {
if (/password-protected/.test(e.message)) {
const password = prompt(
"Please enter the password to open this XLSX file. Press cancel to exit."
);
if (password === null) {
return { data: [], error: "Password required." };
}
try {
const workbook = await XlsxPopulate.fromDataAsync(buffer, { password });
const sheet = workbook.sheet(0);
if (sheet) {
let json = sheet.usedRange().value();
json = _.map(json, (row) => {
return _.map(row, (cell) => {
if (cell) {
return cell.toString();
}
return "";
});
});
return { data: json };
}
} catch (e) {
// follow through to the error below
}
return { data: [], error: "Unable to parse Password protected XLSX" };
}
throw e;
}
}
async function parsePDF(file: File): Promise<Result> {

View File

@ -1,8 +1,16 @@
import { sveltekit } from "@sveltejs/kit/vite";
import { nodePolyfills } from "vite-plugin-node-polyfills";
/** @type {import('vite').UserConfig} */
const config = {
plugins: [sveltekit()],
plugins: [
sveltekit(),
nodePolyfills({
globals: {
Buffer: true
}
})
],
server: {
proxy: {
"/api": {