Получение массива имен столбцов в SheetJS

Я пытаюсь разобрать электронную таблицу 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/


person Vytalyi    schedule 15.01.2016    source источник


Ответы (6)


Преобразование алфавитных чисел в JavaScript

Вот немного другой взгляд на буквенно-цифровое преобразование, вдохновленный PHP-решением. Это простой минимальный пример с нулевой проверкой ошибок, просто чтобы выполнить работу.

Нам понадобятся две вспомогательные функции для преобразований. Коды символов для букв алфавита уже находятся в алфавитном порядке в таблице 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 для тестирования (кнопка «повторить» здесь не работает должным образом) результатов, поэтому объем кода немного больше.

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>

person halfzebra    schedule 20.01.2016
comment
Спасибо большое, воспользуюсь вашим решением - person Vytalyi; 21.01.2016
comment
@Vytalyi рад помочь! - person halfzebra; 21.01.2016

Этот код предоставит вам названия заголовков столбцов на всех листах книги.

var XLSX = require('xlsx');
var workbook = XLSX.readFile('./test.xlsx');
var sheet_name_list = workbook.SheetNames;
let columnHeaders = [];
for (var sheetIndex = 0; sheetIndex < sheet_name_list.length; sheetIndex++) {
    var worksheet = workbook.Sheets[sheet_name_list[sheetIndex]];
    for (let key in worksheet) {
        let regEx = new RegExp("^\(\\w\)\(1\){1}$");
        if (regEx.test(key) == true) {
            columnHeaders.push(worksheet[key].v);
        }
    }
}
person Saurabh Bishnoi    schedule 03.07.2019

Вот как я это сделал с помощью 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
        }
    }
 }
person Jyotirmaya Prusty    schedule 27.01.2017
comment
Привет, @Jyotirmaya Prusty. Ваш комментарий мне очень помог! Теперь я изо всех сил пытаюсь получить остальную часть своего стола. Имена столбцов отображаются правильно, но я не знаю, как перебрать остальные и отправить их на свой рабочий лист. Не могли бы вы мне помочь? - person sonja; 19.09.2018

Если я правильно понял вопрос, задача состоит в том, чтобы расширить диапазон имен столбцов Excel для диапазона, например ["A1: DD38"].

Диапазон определяет блок столбцов от A до DD и ряды от 1 до 38. И нам нужно только получить развернутый список столбцов:

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

Обратите внимание, что эта строка имен столбцов на самом деле работает как числа. Вы начинаете с «А» и идете к «Я». Затем «B» становится первой цифрой, и мы продолжаем с «A» до «Z» в нулевой цифре и так далее.

Таким образом, имена столбцов на самом деле представляют собой числа в системе счисления 26, где 0 = «A», 1 = «B» и так далее.

В javascript у нас есть Number().toString(radix ) для преобразования числа в другую систему счисления с любым заданным основанием, см. .

Обратное преобразование можно выполнить с помощью parseInt(radix) .

Для системы с основанием 26 javascript использует числа от 0 до 9, а затем строчные буквы от «a» до «p» для остальных символов.

Мы можем переключиться с системы javascript на систему excel («A» на «Z») с простой заменой символов, поскольку системы имеют одинаковую базу.

Итак, наша задача сводится к следующему:

  • Преобразование начальных/конечных столбцов в десятичные значения
  • Итерация от начала до конца
  • Преобразуйте каждое число в систему Excel и добавьте к полученному массиву

Обновление: К сожалению, ситуация не идеальна, у нас есть A...Z, а затем AA ... AZ, а A представляет собой нулевую цифру. Таким образом, в цифрах это похоже на 0..9, затем 00..09 и только потом 10...19, поэтому нам нужно искусственно сымитировать ситуацию 00...09.

Вот jsfiddle с рабочим примером.

person Boris Serebrov    schedule 20.01.2016
comment
@Vytalyi да, я вижу, что мне не хватало части AA...AZ, обновил свой пример с исправлением. - person Boris Serebrov; 21.01.2016

Передайте рабочий лист, и функция вернет массив имен столбцов:

get_header_row(sheet) {
    let headers = [];
    let range = XLSX.utils.decode_range(sheet['!ref']);
    let C, R = range.s.r; /* start in the first row */
    /* walk every column in the range */
    for(C = range.s.c; C <= range.e.c; ++C) {
      let cell = sheet[XLSX.utils.encode_cell({c:C, r:R})] /* find the cell in the first row */

      let hdr = "";
        if(cell && cell.t) hdr = XLSX.utils.format_cell(cell);

        headers.push(hdr);
    }
    return headers;
}

Ссылка: решение взято из Github Issue

Дополнительная информация. Если вы хотите узнать больше об общей структуре, ознакомьтесь с официальная ссылка

person stayingcool    schedule 16.02.2021

Сделал следующее в xlsx v0.16.9

const workbookHeaders = xlsx.readFile(filePath, { sheetRows: 1 });
const columnsArray = xlsx.utils.sheet_to_json(workbookHeaders.Sheets[sheetName], { header: 1 })[0];
person Sharan V K    schedule 25.06.2021