From 2339e1322294ae3c9a67d27d4604be8e94ba5694 Mon Sep 17 00:00:00 2001 From: Anton Alexandrenok Date: Wed, 2 Aug 2017 19:41:44 +0300 Subject: [PATCH] `skipHidden` option for sheet_to_csv (fixes #755) Note: Excel CSV conversion includes hidden rows and columns by default --- README.md | 3 +-- bits/90_utils.js | 12 ++++++++---- docbits/82_util.md | 1 + test.js | 18 ++++++++++++++++++ tests/core.js | 18 ++++++++++++++++++ xlsx.flow.js | 12 ++++++++---- xlsx.js | 12 ++++++++---- 7 files changed, 62 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index d5dfab8..5669232 100644 --- a/README.md +++ b/README.md @@ -1688,6 +1688,7 @@ produces CSV output. The function takes an options argument: | dateNF | fmt 14 | Use specified date format in string output | | strip | false | Remove trailing field separators in each record ** | | blankrows | true | Include blank lines in the CSV output | +| skipHidden | false | Skips hidden rows/columns in the CSV output | - `strip` will remove trailing commas from each line under default `FS/RS` - blankrows must be set to `false` to skip blank lines. @@ -2313,5 +2314,3 @@ granted by the Apache 2.0 License are reserved by the Original Author. - ISO/IEC 29500:2012(E) "Information technology — Document description and processing languages — Office Open XML File Formats" - Open Document Format for Office Applications Version 1.2 (29 September 2011) - Worksheet File Format (From Lotus) December 1984 - - diff --git a/bits/90_utils.js b/bits/90_utils.js index 0082cbe..0e773be 100644 --- a/bits/90_utils.js +++ b/bits/90_utils.js @@ -81,8 +81,9 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ var qreg = /"/g; function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ { var isempty = true; - var row = "", txt = "", rr = encode_row(R); + var row = [], txt = "", rr = encode_row(R); for(var C = r.s.c; C <= r.e.c; ++C) { + if (!cols[C]) continue; var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr]; if(val == null) txt = ""; else if(val.v != null) { @@ -95,10 +96,10 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; } else txt = ""; /* NOTE: Excel CSV does not support array formulae */ - row += (C === r.s.c ? "" : FS) + txt; + row.push(txt); } if(o.blankrows === false && isempty) return null; - return row; + return row.join(FS); } function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ { @@ -111,8 +112,11 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ { var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); var row = "", cols = []; o.dense = Array.isArray(sheet); - for(var C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); + var colInfos = o.skipHidden ? sheet["!cols"] : undefined; + var rowInfos = o.skipHidden ? sheet["!rows"] : undefined; + for(var C = r.s.c; C <= r.e.c; ++C) if (!colInfos || !colInfos[C] || !colInfos[C].hidden) cols[C] = encode_col(C); for(var R = r.s.r; R <= r.e.r; ++R) { + if (rowInfos && rowInfos[R] && rowInfos[R].hidden) continue; row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o); if(row == null) { continue; } if(o.strip) row = row.replace(endregex,""); diff --git a/docbits/82_util.md b/docbits/82_util.md index b619542..d4787ee 100644 --- a/docbits/82_util.md +++ b/docbits/82_util.md @@ -123,6 +123,7 @@ produces CSV output. The function takes an options argument: | dateNF | fmt 14 | Use specified date format in string output | | strip | false | Remove trailing field separators in each record ** | | blankrows | true | Include blank lines in the CSV output | +| skipHidden | false | Skips hidden rows/columns in the CSV output | - `strip` will remove trailing commas from each line under default `FS/RS` - blankrows must be set to `false` to skip blank lines. diff --git a/test.js b/test.js index 537e23c..abdcd72 100644 --- a/test.js +++ b/test.js @@ -1780,6 +1780,24 @@ describe('csv', function() { assert.equal(wb.Sheets.Sheet1['!ref'], "A1:B3"); }); }); + it('should handle skipHidden for rows if requested', function() { + var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n"; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + ws["!rows"] = [null,{hidden:true},null,null]; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + assert.equal(X.utils.sheet_to_csv(ws, {skipHidden:true}), "1,2,3,\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n"); + delete ws["!rows"]; + }); + it('should handle skipHidden for columns if requested', function() { + var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n"; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + ws["!cols"] = [null,{hidden:true},null,null]; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + assert.equal(X.utils.sheet_to_csv(ws, {skipHidden:true}), "1,3,\nTRUE,,sheetjs\nfoo,2/19/14,0.3\n,,\nbaz,qux,\n"); + ws["!cols"] = [{hidden:true},null,null,null]; + assert.equal(X.utils.sheet_to_csv(ws, {skipHidden:true}), "2,3,\nFALSE,,sheetjs\nbar,2/19/14,0.3\n,,\n,qux,\n"); + delete ws["!cols"]; + }); }); }); diff --git a/tests/core.js b/tests/core.js index 681936c..4e8ac02 100644 --- a/tests/core.js +++ b/tests/core.js @@ -1791,6 +1791,24 @@ describe('csv', function() { assert.equal(wb.Sheets.Sheet1['!ref'], "A1:B3"); }); }); + it('should handle skipHidden for rows if requested', function() { + var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n"; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + ws["!rows"] = [null,{hidden:true},null,null]; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + assert.equal(X.utils.sheet_to_csv(ws, {skipHidden:true}), "1,2,3,\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n"); + delete ws["!rows"]; + }); + it('should handle skipHidden for columns if requested', function() { + var baseline = "1,2,3,\nTRUE,FALSE,,sheetjs\nfoo,bar,2/19/14,0.3\n,,,\nbaz,,qux,\n"; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + ws["!cols"] = [null,{hidden:true},null,null]; + assert.equal(X.utils.sheet_to_csv(ws), baseline); + assert.equal(X.utils.sheet_to_csv(ws, {skipHidden:true}), "1,3,\nTRUE,,sheetjs\nfoo,2/19/14,0.3\n,,\nbaz,qux,\n"); + ws["!cols"] = [{hidden:true},null,null,null]; + assert.equal(X.utils.sheet_to_csv(ws, {skipHidden:true}), "2,3,\nFALSE,,sheetjs\nbar,2/19/14,0.3\n,,\n,qux,\n"); + delete ws["!cols"]; + }); }); }); diff --git a/xlsx.flow.js b/xlsx.flow.js index 03da3ad..ac5032c 100644 --- a/xlsx.flow.js +++ b/xlsx.flow.js @@ -17817,8 +17817,9 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/){ var qreg = /"/g; function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Array*/, fs/*:number*/, rs/*:number*/, FS/*:string*/, o/*:Sheet2CSVOpts*/)/*:?string*/ { var isempty = true; - var row = "", txt = "", rr = encode_row(R); + var row = [], txt = "", rr = encode_row(R); for(var C = r.s.c; C <= r.e.c; ++C) { + if (!cols[C]) continue; var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr]; if(val == null) txt = ""; else if(val.v != null) { @@ -17831,10 +17832,10 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; } else txt = ""; /* NOTE: Excel CSV does not support array formulae */ - row += (C === r.s.c ? "" : FS) + txt; + row.push(txt); } if(o.blankrows === false && isempty) return null; - return row; + return row.join(FS); } function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ { @@ -17847,8 +17848,11 @@ function sheet_to_csv(sheet/*:Worksheet*/, opts/*:?Sheet2CSVOpts*/)/*:string*/ { var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); var row = "", cols = []; o.dense = Array.isArray(sheet); - for(var C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); + var colInfos = o.skipHidden ? sheet["!cols"] : undefined; + var rowInfos = o.skipHidden ? sheet["!rows"] : undefined; + for(var C = r.s.c; C <= r.e.c; ++C) if (!colInfos || !colInfos[C] || !colInfos[C].hidden) cols[C] = encode_col(C); for(var R = r.s.r; R <= r.e.r; ++R) { + if (rowInfos && rowInfos[R] && rowInfos[R].hidden) continue; row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o); if(row == null) { continue; } if(o.strip) row = row.replace(endregex,""); diff --git a/xlsx.js b/xlsx.js index 55cf361..a0f075b 100644 --- a/xlsx.js +++ b/xlsx.js @@ -17727,8 +17727,9 @@ function sheet_to_json(sheet, opts){ var qreg = /"/g; function make_csv_row(sheet, r, R, cols, fs, rs, FS, o) { var isempty = true; - var row = "", txt = "", rr = encode_row(R); + var row = [], txt = "", rr = encode_row(R); for(var C = r.s.c; C <= r.e.c; ++C) { + if (!cols[C]) continue; var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr]; if(val == null) txt = ""; else if(val.v != null) { @@ -17741,10 +17742,10 @@ function make_csv_row(sheet, r, R, cols, fs, rs, FS, o) { txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; } else txt = ""; /* NOTE: Excel CSV does not support array formulae */ - row += (C === r.s.c ? "" : FS) + txt; + row.push(txt); } if(o.blankrows === false && isempty) return null; - return row; + return row.join(FS); } function sheet_to_csv(sheet, opts) { @@ -17757,8 +17758,11 @@ function sheet_to_csv(sheet, opts) { var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); var row = "", cols = []; o.dense = Array.isArray(sheet); - for(var C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); + var colInfos = o.skipHidden ? sheet["!cols"] : undefined; + var rowInfos = o.skipHidden ? sheet["!rows"] : undefined; + for(var C = r.s.c; C <= r.e.c; ++C) if (!colInfos || !colInfos[C] || !colInfos[C].hidden) cols[C] = encode_col(C); for(var R = r.s.r; R <= r.e.r; ++R) { + if (rowInfos && rowInfos[R] && rowInfos[R].hidden) continue; row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o); if(row == null) { continue; } if(o.strip) row = row.replace(endregex,"");