在SheetJS中获取一个列名称的数组

我试图parsing一个Excel电子表格(.xlsx)到JSON。

我正在使用SheetJS节点包。

然而,我不能实现这样一个简单的事情 – 我如何获得与内部存储相同的格式的列名称?

以下是我的代码:

function _buildColumnsArray(range) { // range = "A1:CA38" // ... // should return ['A', ..., 'Z', 'AA', ..., 'AZ', 'BA', ..., 'BZ', 'CA'...] } // -------- var workbook = XLSX.readFile(fileUrl), sheets = workbook.Sheets, result = {}; result.sheetNames = []; for (var i = 0; i < workbook.SheetNames.length; i++) { var sheet = workbook.Sheets[workbook.SheetNames[i]], csvSheet = XLSX.utils.sheet_to_csv(sheet); // '!ref' referring to a specific range by docs if (sheet["!ref"]) { var columns = _buildColumnsArray(sheet["!ref"]), rows = _buildRowsArray(columns, csvSheet); // build final result result[workbook.SheetNames[i]] = { columns: columns, rows: rows }; result.sheetNames.push(workbook.SheetNames[i]); } } 

这是我目前正在尝试哪些不完美的工作: https : //jsfiddle.net/t8hej9hu/

在JavaScript中的字母数字转换

在PHP解决scheme的启发下,这里有一些不同的字母数字转换。 这只是一个简单的例子,只是为了完成这个工作而没有错误的检查。

我们需要两个辅助函数来进行转换。 字母表中的字符代码在Unicode表中已经按字母顺序排列,所以我们只需要在转换时添加或删除偏移量。

 function alphaToNum(alpha) { var i = 0, num = 0, len = alpha.length; for (; i < len; i++) { num = num * 26 + alpha.charCodeAt(i) - 0x40; } return num - 1; } 

另一个用于将数字转换为字母数字。

 function numToAlpha(num) { var alpha = ''; for (; num >= 0; num = parseInt(num / 26, 10) - 1) { alpha = String.fromCharCode(num % 26 + 0x41) + alpha; } return alpha; } 

_buildColumnsArray函数的最终版本:

 function _buildColumnsArray(range) { var i, res = [], rangeNum = range.split(':').map(function(val) { return alphaToNum(val.replace(/[0-9]/g, '')); }), start = rangeNum[0], end = rangeNum[1] + 1; for (i = start; i < end ; i++) { res.push(numToAlpha(i)); } return res; } 

返回的数组必须与MS Excel中的列名完全相同:

 ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ', 'BA', 'BB', 'BC', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BK', 'BL', 'BM', 'BN', 'BO', 'BP', 'BQ', 'BR', 'BS', 'BT', 'BU', 'BV', 'BW', 'BX', 'BY', 'BZ', 'CA'] 

下面是一个工作示例,我一直在使用Mocha和Chai来testing(“重播”button的行为不像预期的那样)结果,所以代码量有点大。

 function alphaToNum(alpha) { var i = 0, num = 0, len = alpha.length; for (; i < len; i++) { num = num * 26 + alpha.charCodeAt(i) - 0x40; } return num - 1; } function numToAlpha(num) { var alpha = ''; for (; num >= 0; num = parseInt(num / 26, 10) - 1) { alpha = String.fromCharCode(num % 26 + 0x41) + alpha; } return alpha; } function _buildColumnsArray(range) { var i, res = [], rangeNum = range.split(':').map(function(val) { return alphaToNum(val.replace(/[0-9]/g, '')); }), start = rangeNum[0], end = rangeNum[1] + 1; for (i = start; i < end ; i++) { res.push(numToAlpha(i)); } return res; } mocha.setup('bdd'); chai.should(); describe('Alphabet Numbers with base 26', function() { describe('alphaToNum', function() { it('alphaToNum(\'A\') should be equal 0', function() { alphaToNum('A').should.equal(0); }); it('alphaToNum(\'HELLO\') should be equal 3752126', function() { alphaToNum('HELLO').should.equal(3752126); }); }); describe('numToAlpha', function() { it('numToAlpha(3) should be equal \'D\'', function() { numToAlpha(3).should.equal('D'); }); it('numToAlpha(1337) should be equal 3752126', function() { numToAlpha(1337).should.equal('AYL'); }); }); describe('Alphabet Numbers range', function() { it('_buildColumnsArray(\'B10:K10\') should be deep equal [ \'B\', \'C\', \'D\', \'E\', \'F\', \'G\' , \'H\']', function() { _buildColumnsArray('B10:H10').should.deep.equal(['B', 'C', 'D', 'E', 'F', 'G', 'H']); }); it('_buildColumnsArray(\'A1: CA38\') should be equal [\'A\', \'B\', \'C\', \'D\', \'E\', \'F\', \'G\', \'H\', \'I\', \'J\', \'K\', \'L\', \'M\', \'N\', \'O\', \'P\', \'Q\', \'R\', \'S\', \'T\', \'U\', \'V\', \'W\', \'X\', \'Y\', \'Z\', \'AA\', \'AB\', \'AC\', \'AD\', \'AE\', \'AF\', \'AG\', \'AH\', \'AI\', \'AJ\', \'AK\', \'AL\', \'AM\', \'AN\', \'AO\', \'AP\', \'AQ\', \'AR\', \'AS\', \'AT\', \'AU\', \'AV\', \'AW\', \'AX\', \'AY\', \'AZ\', \'BA\', \'BB\', \'BC\', \'BD\', \'BE\', \'BF\', \'BG\', \'BH\', \'BI\', \'BJ\', \'BK\', \'BL\', \'BM\', \'BN\', \'BO\', \'BP\', \'BQ\', \'BR\', \'BS\', \'BT\', \'BU\', \'BV\', \'BW\', \'BX\', \'BY\', \'BZ\', \'CA\']', function() { _buildColumnsArray('A1:CA38').should.deep.equal(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ', 'BA', 'BB', 'BC', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BK', 'BL', 'BM', 'BN', 'BO', 'BP', 'BQ', 'BR', 'BS', 'BT', 'BU', 'BV', 'BW', 'BX', 'BY', 'BZ', 'CA']); }); }); }); mocha.run(); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.4.1/chai.min.js"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.js"></script> <div id="mocha"></div> 

如果我正确地得到了这个问题,那么任务就是展开[“A1:DD38”]范围的Excel列名范围。

范围定义了从A到DD和1到38行的列块。我们只需要得到一个列的列表:

 A, B, ... Z, AA, AB, ..., AZ, BA, ... BZ, ... 

请注意,这一行的列名实际上是作为数字。 你从“A”开始,然后转到“Z”。 然后“B”变成第一位数字,我们继续在零位数字“A”到“Z”,依此类推。

所以列名实际上代表26-基数系统中的数字,其中0 =“A”,1 =“B”等。

在JavaScript中,我们有Number().toString(radix)方法来将数字转换为具有任何给定基数的另一个数字系统,请参阅。

反转换可以用parseInt(radix)完成 。

对于基数为26的系统,javascript使用0到9之间的数字,其余的符号使用小写字母从“a”到“p”。

因为系统具有相同的基础,我们可以用简单的字符replace从javascript系统切换到excel系统(“A”到“Z”)。

所以我们的任务减到这个:

  • 将开始/结束列转换为十进制值
  • 从头到尾迭代
  • 将每个数字转换为Excel系统并添加到结果数组中

更新 :不幸的是,情况并不理想,我们有A...Z然后AA ... AZ ,而A代表零位。 所以在数字上就像是0..9 ,然后是00..09 ,然后是10...19 ,所以我们需要人为地模拟00...09情况。

这里是工作示例jsfiddle 。

这是我如何使用SheetJS。

 var colValues =[]; function checkCols(workbook) //your workbook variable { var first_sheet_name = workbook.SheetNames[0]; var worksheet = workbook.Sheets[first_sheet_name]; var cells = Object.keys(worksheet); for (var i = 0; i < Object.keys(cells).length; i++) { if( cells[i].indexOf('1') > -1) { colValues.push(worksheet[cells[i]].v); //Contails all column names } } }