From 20f22cf7f936fa895dd452ff3fdaecc1aa3a19d9 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Mon, 19 Jun 2017 03:14:14 -0400 Subject: [PATCH] vue demo and typing fixes [ci skip] --- README.md | 1 + demos/angular/SheetJS-angular.js | 26 ++++----- demos/vue/README.md | 20 +++++++ demos/vue/SheetJS-vue.js | 63 ++++++++++++++++++++++ demos/vue/index.html | 51 ++++++++++++++++++ demos/vue/xlsx.full.min.js | 1 + demos/webpack/README.md | 12 +++++ demos/webpack/webpack.config.js | 6 +++ docbits/10_install.md | 1 + types/index.d.ts | 91 +++++++++++++++++++++++++++----- types/write.ts | 13 ++++- 11 files changed, 258 insertions(+), 27 deletions(-) create mode 100644 demos/vue/README.md create mode 100644 demos/vue/SheetJS-vue.js create mode 100644 demos/vue/index.html create mode 120000 demos/vue/xlsx.full.min.js diff --git a/README.md b/README.md index 3a61605..db9722e 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,7 @@ The `demos` directory includes sample projects for: - [`requirejs`](demos/requirejs/) - [`rollup`](demos/rollup/) - [`systemjs`](demos/systemjs/) +- [`vue 2`](demos/vue/) - [`webpack`](demos/webpack/) ### Optional Modules diff --git a/demos/angular/SheetJS-angular.js b/demos/angular/SheetJS-angular.js index d97a780..74523ad 100644 --- a/demos/angular/SheetJS-angular.js +++ b/demos/angular/SheetJS-angular.js @@ -7,7 +7,7 @@ function SheetJSExportService(uiGridExporterService) { var fileName = gridApi.grid.options.filename || 'SheetJS'; fileName += wopts.bookType ? "." + wopts.bookType : '.xlsx'; - + var sheetName = gridApi.grid.options.sheetname || 'Sheet1'; var wb = XLSX.utils.book_new(), ws = uigrid_to_sheet(data, columns); @@ -63,15 +63,15 @@ function SheetJSExportService(uiGridExporterService) { } var SheetJSImportDirective = function() { - return { + return { scope: { opts: '=' }, - link: function ($scope, $elm, $attrs) { - $elm.on('change', function (changeEvent) { - var reader = new FileReader(); + link: function ($scope, $elm, $attrs) { + $elm.on('change', function (changeEvent) { + var reader = new FileReader(); - reader.onload = function (e) { + reader.onload = function (e) { /* read workbook */ - var bstr = e.target.result; + var bstr = e.target.result; var wb = XLSX.read(bstr, {type:'binary'}); /* grab first sheet */ @@ -98,10 +98,10 @@ var SheetJSImportDirective = function() { $scope.opts.columnDefs = cols; $scope.opts.data = data; }); - }; - - reader.readAsBinaryString(changeEvent.target.files[0]); - }); - } - } + }; + + reader.readAsBinaryString(changeEvent.target.files[0]); + }); + } + } } diff --git a/demos/vue/README.md b/demos/vue/README.md new file mode 100644 index 0000000..ee8f3d9 --- /dev/null +++ b/demos/vue/README.md @@ -0,0 +1,20 @@ +# VueJS 2 + +The `xlsx.core.min.js` and `xlsx.full.min.js` scripts are designed to be dropped +into web pages with script tags e.g. + +```html + +``` + +Strictly speaking, there should be no need for a Vue.JS demo! You can proceed +as you would with any other browser-friendly library. + +This demo directly generates HTML using `sheet_to_html` and adds an element to +a pregenerated template. It also has a button for exporting as XLSX. + + +## Single File Components + +For Single File Components, a simple `import XLSX from 'xlsx'` should suffice. +The webpack demo includes a sample `webpack.config.js`. diff --git a/demos/vue/SheetJS-vue.js b/demos/vue/SheetJS-vue.js new file mode 100644 index 0000000..926d6b5 --- /dev/null +++ b/demos/vue/SheetJS-vue.js @@ -0,0 +1,63 @@ +var SheetJSFT = [ + "xlsx", "xlsb", "xlsm", "xls", "xml", "csv", "txt", "ods", "fods", "uos", "sylk", "dif", "dbf", "prn", "qpw", "123", "wb*", "wq*", "html", "htm" +].map(function(x) { return "." + x; }).join(","); + +var SJSTemplate = [ + '
', + '', + '
', + '', + '
', + '
', + '
' +].join(""); + +function s2ab(s) { + if(typeof ArrayBuffer !== 'undefined') { + var buf = new ArrayBuffer(s.length); + var view = new Uint8Array(buf); + for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; + return buf; + } else { + var buf = new Array(s.length); + for (var i=0; i!=s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF; + return buf; + } +} + +Vue.component('html-preview', { + template: SJSTemplate, + methods: { + onchange: function(evt) { + var reader = new FileReader(); + reader.onload = function (e) { + /* read workbook */ + var bstr = e.target.result; + var wb = XLSX.read(bstr, {type:'binary'}); + + /* grab first sheet */ + var wsname = wb.SheetNames[0]; + var ws = wb.Sheets[wsname]; + + /* generate HTML */ + var HTML = XLSX.utils.sheet_to_html(ws); + + /* update table */ + document.getElementById('out-table').innerHTML = HTML; + /* show export button */ + document.getElementById('expor-table').style.visibility = "visible"; + }; + + reader.readAsBinaryString(evt.target.files[0]); + }, + onexport: function(evt) { + /* generate workbook object from table */ + var wb = XLSX.utils.table_to_book(document.getElementById('out-table')); + /* get binary string as output */ + var wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' }); + + /* force a download */ + saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), "sheetjs.xlsx"); + } + } +}); diff --git a/demos/vue/index.html b/demos/vue/index.html new file mode 100644 index 0000000..288492a --- /dev/null +++ b/demos/vue/index.html @@ -0,0 +1,51 @@ + + + + + + SheetJS + VueJS2 + + + + + + + + + + + + + + + +
+SheetJS + VueJS2 demo
+
+The core library can be used as-is in Vue applications.
+The Community Edition README details some common use cases.
+We also have some more public demos
+
+This demo shows a sample Vue component "html-preview" that:
+- displays a file input that accepts a spreadsheet file
+- draws the first worksheet of a submitted file as HTML
+- presents an export button to generate XLSX files
+
+Sample Spreadsheet
+
+ +
+ +
+ + + + + diff --git a/demos/vue/xlsx.full.min.js b/demos/vue/xlsx.full.min.js new file mode 120000 index 0000000..dbca48d --- /dev/null +++ b/demos/vue/xlsx.full.min.js @@ -0,0 +1 @@ +../../dist/xlsx.full.min.js \ No newline at end of file diff --git a/demos/webpack/README.md b/demos/webpack/README.md index 6a98824..f33eefb 100644 --- a/demos/webpack/README.md +++ b/demos/webpack/README.md @@ -28,3 +28,15 @@ convince webpack, set `output` in the webpack config: library: 'XLSX' } ``` + +## Omitting optional dependencies + +The `codepage` is needed in certain special cases, including files generated by +non-US-English versions of Excel, but may not be needed. To reduce build size, +the module can be omitted by aliasing the dependency: + +```js + resolve: { + alias: { "./dist/cpexcel.js": "" } + }, +``` diff --git a/demos/webpack/webpack.config.js b/demos/webpack/webpack.config.js index 6fbaa28..1fa5d72 100644 --- a/demos/webpack/webpack.config.js +++ b/demos/webpack/webpack.config.js @@ -3,6 +3,12 @@ module.exports = { libraryTarget: 'var', library: 'XLSX' }, + /* Uncomment the next block to suppress codepage */ + /* + resolve: { + alias: { "./dist/cpexcel.js": "" } + }, + */ node: { fs: false, process: false, diff --git a/docbits/10_install.md b/docbits/10_install.md index 87c74fd..818834a 100644 --- a/docbits/10_install.md +++ b/docbits/10_install.md @@ -33,6 +33,7 @@ The `demos` directory includes sample projects for: - [`requirejs`](demos/requirejs/) - [`rollup`](demos/rollup/) - [`systemjs`](demos/systemjs/) +- [`vue 2`](demos/vue/) - [`webpack`](demos/webpack/) ### Optional Modules diff --git a/types/index.d.ts b/types/index.d.ts index 254b8a1..5280e4c 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -13,7 +13,9 @@ export function writeFile(data: WorkBook, filename: string, opts?: WritingOption /** Attempts to write the workbook data */ export function write(data: WorkBook, opts?: WritingOptions): any; +/** Utility Functions */ export const utils: XLSX$Utils; +/** Stream Utility Functions */ export const stream: StreamUtils; /** Number Format (either a string or an index to the format table) */ @@ -223,10 +225,18 @@ export interface SheetProps { Hidden?: 0 | 1 | 2; } +/** Defined Name Object */ export interface DefinedName { + /** Name */ Name: string; + + /** Reference */ Ref: string; + + /** Scope (undefined for workbook scope) */ Sheet?: number; + + /** Name comment */ Comment?: string; } @@ -251,6 +261,7 @@ export interface WorkbookProperties { filterPrivacy?: boolean; } +/** Column Properties Object */ export interface ColInfo { /* --- visibility --- */ @@ -271,6 +282,8 @@ export interface ColInfo { /** Excel's "Max Digit Width" unit, always integral */ MDW?: number; } + +/** Row Properties Object */ export interface RowInfo { /* --- visibility --- */ @@ -414,25 +427,33 @@ export interface AutoFilterInfo { } export type WSKeys = SheetKeys | ColInfo[] | RowInfo[] | Range[] | ProtectInfo | AutoFilterInfo; -/** - * object representing the worksheet - */ +/** Worksheet Object */ export interface WorkSheet extends Sheet { /** * Indexing with a cell address string maps to a cell object * Special keys start with '!' */ [cell: string]: CellObject | WSKeys | any; + + /** Column Info */ '!cols'?: ColInfo[]; + + /** Row Info */ '!rows'?: RowInfo[]; + + /** Merge Ranges */ '!merges'?: Range[]; + + /** Worksheet Protection info */ '!protect'?: ProtectInfo; + + /** AutoFilter info */ '!autofilter'?: AutoFilterInfo; } /** * The Excel data type for a cell. - * b Boolean, n Number, e error, s String, d Date + * b Boolean, n Number, e error, s String, d Date, z Stub */ export type ExcelDataType = 'b' | 'n' | 'e' | 's' | 'd' | 'z'; @@ -442,6 +463,7 @@ export type ExcelDataType = 'b' | 'n' | 'e' | 's' | 'd' | 'z'; */ export type BookType = 'xlsx' | 'xlsm' | 'xlsb' | 'biff2' | 'xlml' | 'ods' | 'fods' | 'csv' | 'txt' | 'sylk' | 'html' | 'dif' | 'prn'; +/** Comment element */ export interface Comment { /** Author of the comment block */ a?: string; @@ -450,6 +472,7 @@ export interface Comment { t: string; } +/** Link object */ export interface Hyperlink { /** Target of the link (HREF) */ Target: string; @@ -458,6 +481,7 @@ export interface Hyperlink { Tooltip?: string; } +/** Worksheet Cell Object */ export interface CellObject { /** The raw value of the cell. Can be omitted if a formula is specified */ v?: string | number | boolean | Date; @@ -496,6 +520,7 @@ export interface CellObject { s?: object; } +/** Simple Cell Address */ export interface CellAddress { /** Column number */ c: number; @@ -525,24 +550,36 @@ export interface Sheet2CSVOpts { } export interface Sheet2HTMLOpts { + /** Add contenteditable to every cell */ editable?: boolean; + /** Header HTML */ header?: string; + /** Footer HTML */ footer?: string; } export interface Sheet2JSONOpts { - /** Use specified date format */ + /** Use specified format for date cells */ dateNF?: NumberFormat; + /** Output format */ header?: "A"|number|string[]; + /** Override worksheet range */ range?: any; + /** Include or omit blank lines in the output */ + blankrows?: boolean; + + /** Default value for null/undefined values */ + defval?: any; + + /** if true, return raw data; if false, return formatted text */ raw?: boolean; } export interface AOA2SheetOpts { - /** Use specified date format */ + /** Use specified format for date cells */ dateNF?: NumberFormat; /** @@ -568,9 +605,7 @@ export interface Table2SheetOpts { dateNF?: NumberFormat; } -/** - * General utilities - */ +/** General utilities */ export interface XLSX$Utils { /* --- Import Functions --- */ @@ -629,13 +664,43 @@ export interface XLSX$Utils { /** Converts A1 range to 0-indexed form */ decode_range(range: string): Range; - /* --- WorkBook Utilities --- */ + /* --- General Utilities --- */ - /** Creates a new WorkBook */ + /** Creates a new workbook */ book_new(): WorkBook; - /** Appends worksheet to given workbook (blank name will enumerate Sheet# to find unused name) */ - book_append_sheet(wb: WorkBook, ws: WorkSheet, name?: String): void; + /** Append a worksheet to a workbook */ + book_append_sheet(workbook: WorkBook, worksheet: WorkSheet, name?: string): void; + + /** Set sheet visibility (visible/hidden/very hidden) */ + book_set_sheet_visibility(workbook: WorkBook, sheet: number|string, visibility: number): void; + + /** Set number format for a cell */ + cell_set_number_format(cell: CellObject, fmt: string|number): CellObject; + + /** Set hyperlink for a cell */ + cell_set_hyperlink(cell: CellObject, target: string, tooltip?: string): CellObject; + + /** Add comment to a cell */ + cell_add_comment(cell: CellObject, text: string, author?: string): void; + + /** Assign an Array Formula to a range */ + sheet_set_array_formula(ws: WorkSheet, range: Range|string, formula: string): WorkSheet; + + consts: XLSX$Consts; +} + +export interface XLSX$Consts { + /* --- Sheet Visibility --- */ + + /** Visibility: Visible */ + SHEET_VISIBLE: 0; + + /** Visibility: Hidden */ + SHEET_HIDDEN: 1; + + /** Visibility: Very Hidden */ + SHEET_VERYHIDDEN: 2; } /** NODE ONLY! these return Readable Streams */ diff --git a/types/write.ts b/types/write.ts index 5fde037..ae83389 100644 --- a/types/write.ts +++ b/types/write.ts @@ -38,12 +38,13 @@ console.log("Columns :"); for(i = 0; i !== wscols.length; ++i) console.log(wscols[i]); /* require XLSX */ -import XLSX = require('xlsx'); +import * as XLSX from 'xlsx'; /* blank workbook constructor */ let wb: XLSX.WorkBook = { SheetNames: [], Sheets: {} }; +wb = XLSX.utils.book_new(); /* convert an array of arrays in JS to a CSF spreadsheet */ let ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(data, {cellDates:true}); @@ -51,6 +52,7 @@ let ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(data, {cellDates:true}); /* TEST: add worksheet to workbook */ wb.SheetNames.push(ws_name); wb.Sheets[ws_name] = ws; +XLSX.utils.book_append_sheet(wb, ws, ws_name); /* TEST: simple formula */ (ws['C1']).f = "A1+B1"; @@ -60,12 +62,14 @@ ws['C2'] = {t:'n', f:"A1+B1"}; ws['D1'] = {t:'n', f:"SUM(A1:C1*A1:C1)", F:"D1:D1"}; +XLSX.utils.sheet_set_array_formula(ws, 'D1:D1', "SUM(A1:C1*A1:C1)"); /* TEST: multi-cell array formula */ ws['E1'] = {t:'n', f:"TRANSPOSE(A1:D1)", F:"E1:E4"}; ws['E2'] = {t:'n', F:"E1:E4"}; ws['E3'] = {t:'n', F:"E1:E4"}; ws['E4'] = {t:'n', F:"E1:E4"}; +XLSX.utils.sheet_set_array_formula(ws, 'E1:E4', "TRANSPOSE(A1:D1)"); ws["!ref"] = "A1:E6"; /* TEST: column props */ @@ -76,13 +80,16 @@ ws['!rows'] = wsrows; /* TEST: hyperlink note: Excel does not automatically style hyperlinks */ (ws['A3']).l = { Target: "http://sheetjs.com", Tooltip: "Visit us " }; +XLSX.utils.cell_set_hyperlink(ws['A3'], "http://sheetjs.com", "Visit us " ); /* TEST: built-in format */ (ws['B1']).z = "0%"; // Format Code 9 +XLSX.utils.cell_set_number_format(ws['B1'], "0%"); /* TEST: custom format */ const custfmt = "\"This is \"\\ 0.0"; (ws['C2']).z = custfmt; +XLSX.utils.cell_set_number_format(ws['C2'], custfmt); /* TEST: page margins */ ws['!margins'] = { left:1.0, right:1.0, top:1.0, bottom:1.0, header:0.5, footer:0.5 }; @@ -95,6 +102,9 @@ wb.SheetNames.push("Hidden"); wb.Sheets["Hidden"] = XLSX.utils.aoa_to_sheet(["Hidden".split(""), [1,2,3]]); wb.Workbook = {Sheets:[]}; wb.Workbook.Sheets[1] = {Hidden:1}; +const data_2 = ["Hidden".split(""), [1,2,3]]; +XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(data_2), "Hidden"); +XLSX.utils.book_set_sheet_visibility(wb, "Hidden", XLSX.utils.consts.SHEET_HIDDEN); /* TEST: properties */ wb.Props = { @@ -115,6 +125,7 @@ wb.Props = { (ws['A4']).c = []; (ws['A4']).c.push({a:"SheetJS",t:"I'm a little comment, short and stout!\n\nWell, Stout may be the wrong word"}); +XLSX.utils.cell_add_comment(ws['A4'], "I'm a little comment, short and stout!\n\nWell, Stout may be the wrong word", "SheetJS"); /* TEST: sheet protection */ ws['!protect'] = {