使用Node解析XLSX并创建json

时间:2015-06-16 06:05:07

标签: javascript json node.js excel xlsx

好的,所以我发现这个node_module [ { "id": 1, "Headline": "Team: Sally Pearson", "Location": "Austrailia", "BodyText": "...", "Media: "..." }, { "id": 2, "Headline": "Team: Rebeca Andrade", "Location": "Brazil", "BodyText": "...", "Media: "..." } ] 名为js-xlsx

问题:如何解析xlsx以输出json

以下是excel表格的内容:

enter image description here

最后json应该是这样的:

if(typeof require !== 'undefined') {
    console.log('hey');
    XLSX = require('xlsx');
}
var workbook = XLSX.readFile('./assets/visa.xlsx');
var sheet_name_list = workbook.SheetNames;
sheet_name_list.forEach(function(y) { /* iterate through sheets */
  var worksheet = workbook.Sheets[y];
  for (z in worksheet) {
    /* all keys that do not begin with "!" correspond to cell addresses */
    if(z[0] === '!') continue;
    // console.log(y + "!" + z + "=" + JSON.stringify(worksheet[z].v));

  }

});
XLSX.writeFile(workbook, 'out.xlsx');

index.js:

public TransferFrom() {
    count=1;
    setTitle("Transfer Form");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 924, 571);
    pane = new JPanel();
    pane.setBorder(new EmptyBorder(5, 5, 5, 5));
    pane.setBackground(Color.decode("#5388BE"));
    setContentPane(pane);
    pane.setLayout(null);

    trans_pln_name= new JTextField[30];
    trans_pln_num= new JTextField[30];
    trans_amt= new JTextField[30];
    trans_inv_name= new JTextField[30];
    trans_clr=new JButton[30];
    trans_add=new JButton[30];

    JLabel lblNewLabel = new JLabel("Transfer Form Page");
    lblNewLabel.setForeground(new Color(240, 248, 255));
    lblNewLabel.setBackground(Color.decode("#2c3e50"));
    lblNewLabel.setBounds(0, 0, 1000, 40);
    lblNewLabel.setFont(new Font("Tahoma", Font.BOLD, 20));
    lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
    pane.add(lblNewLabel);

    JLabel lbl1 = new JLabel("Action");
    lbl1.setBounds(300, 95, 150, 30);
    pane.add(lbl1);

    JLabel lbl2 = new JLabel("Begin Date");
    lbl2.setBounds(300, 139, 150, 30);
    pane.add(lbl2);

    JLabel lbl3 = new JLabel("Frequency");
    lbl3.setBounds(300, 183, 150, 30);
    pane.add(lbl3);

    JLabel lbl4 = new JLabel("$ or %");
    lbl4.setBounds(300, 227, 150, 30);
    pane.add(lbl4);

    JLabel lbl5 = new JLabel("Future Transaction Day");
    lbl5.setBounds(300, 272, 150, 30);
    pane.add(lbl5);
    String[] action = { "Custom Transfer","Simple Transfer"};
    trans_comboBox_3 = new JComboBox(action);
    trans_comboBox_3.setSelectedIndex(0);
    trans_comboBox_3.setBounds(470, 95, 180, 33);


    pane.add(trans_comboBox_3);

    String[] freq = {"Once", "Monthly","Quarterly","Semi-Annually","Annually"}; 
    String[] dollar = { "Dollar", "Percent"};   
    trans_comboBox_4 = new JComboBox(freq);
    trans_comboBox_4.setSelectedIndex(0);
    trans_comboBox_4.setBounds(470, 183, 180, 33);
    pane.add(trans_comboBox_4);

    trans_comboBox_1 = new JComboBox(dollar);
    trans_comboBox_1.setSelectedIndex(1);
    trans_comboBox_1.setBounds(470, 227, 180, 33);
    pane.add(trans_comboBox_1);

    trans_comboBox_2 = new JComboBox();
    for(int i=1;i<29;i++)
    {
        trans_comboBox_2.addItem(String.valueOf(i));
    }

    trans_comboBox_2.setSelectedIndex(0);
    trans_comboBox_2.setBounds(470, 272, 180, 33);
    pane.add(trans_comboBox_2);


    JLabel lblMaritalStatus = new JLabel("On Future Date");
    lblMaritalStatus.setBounds(300, 315, 150, 30);
    pane.add(lblMaritalStatus);

    trans_begin = new JTextField();
    trans_begin.setColumns(10);
    trans_begin.setBounds(470, 139, 180, 33);
    pane.add(trans_begin);

    trans_future = new JTextField();
    trans_future.setColumns(10);
    trans_future.setBounds(470, 320, 180, 33);
    pane.add(trans_future);

    addItem();
    pane.revalidate();

    JButton btnNewButton = new JButton("Create Test Case");
    btnNewButton.setBounds(470, 800, 180, 33);
    btnNewButton.addActionListener(new ActionListener() 
    {
        public void actionPerformed(ActionEvent e) {
            /*assignXML();
        System.out.println(XML);
        XMLPath=new String[10];
        XMLPath[0]="C:\\Users\\paranja\\Desktop\\UI\\"+main_test_num.getText()+".xml";
        File fileName = new File(XMLPath[0] );
        if(fileName.exists())
        {
            actionDialog = JOptionPane.showConfirmDialog(getContentPane(),
                    "Replace existing file?");
            if (actionDialog == JOptionPane.NO_OPTION)
                return;
        }
        try
        {
            BufferedWriter out = new BufferedWriter(new FileWriter(fileName));

            out.write(XML);
            out.close();
        }
        catch(Exception ex)
        {
            System.err.println("Error: " + ex.getMessage());
        }
        CreateGroovyAndUploadXML create=new CreateGroovyAndUploadXML();
        create.CreateGroovy(XMLPath);
             */}
    });
    pane.add(btnNewButton);



}

private void addItem() {
    // TODO Auto-generated method stub

    pane.revalidate();
    trans_pln_num[count]=new JTextField();
    trans_pln_num[count].setBounds(50, (300+count*100), 100, 50);
    trans_pln_num[count].setColumns(10);
    trans_pln_num[count].setBorder(
            BorderFactory.createTitledBorder("Plan Number"));
    pane.add(trans_pln_num[count]);

    trans_pln_name[count]=new JTextField();
    trans_pln_name[count].setBounds(200, (300+count*100), 100, 50);
    trans_pln_name[count].setColumns(10);
    trans_pln_name[count].setBorder(
            BorderFactory.createTitledBorder("Plan Name"));
    pane.add(trans_pln_name[count]);

    trans_inv_name[count]=new JTextField();
    trans_inv_name[count].setBounds(350, (300+count*100), 200, 50);
    trans_inv_name[count].setColumns(10);
    trans_inv_name[count].setBorder(
            BorderFactory.createTitledBorder("Investment Name"));
    pane.add(trans_inv_name[count]);

    trans_amt[count]=new JTextField();
    trans_amt[count].setBounds(600, (300+count*100), 200, 50);
    trans_amt[count].setColumns(10);
    trans_amt[count].setBorder(
            BorderFactory.createTitledBorder("Amount"));
    pane.add(trans_amt[count]);

    trans_clr[count]=new JButton("Clear");
    trans_clr[count].setBounds(850, (300+count*100), 50, 50);
    pane.add(trans_clr[count]);

    trans_add[count]=new JButton("+");
    trans_add[count].setBounds(950, (300+count*100), 50, 50);
    trans_add[count].addActionListener(new ActionListener() 
    {
        public void actionPerformed(ActionEvent e) {
            count=count+1;
            addItem();
        }
    });
    pane.add(trans_add[count]);
    pane.revalidate();

}

7 个答案:

答案 0 :(得分:70)

您也可以使用

var XLSX = require('xlsx');
var workbook = XLSX.readFile('Master.xlsx');
var sheet_name_list = workbook.SheetNames;
console.log(XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]))

答案 1 :(得分:36)

改进版本&#34; Josh Marinacci&#34;回答,它将读取超出Z列(即AA1)。

var XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx');
var sheet_name_list = workbook.SheetNames;
sheet_name_list.forEach(function(y) {
    var worksheet = workbook.Sheets[y];
    var headers = {};
    var data = [];
    for(z in worksheet) {
        if(z[0] === '!') continue;
        //parse out the column, row, and value
        var tt = 0;
        for (var i = 0; i < z.length; i++) {
            if (!isNaN(z[i])) {
                tt = i;
                break;
            }
        };
        var col = z.substring(0,tt);
        var row = parseInt(z.substring(tt));
        var value = worksheet[z].v;

        //store header names
        if(row == 1 && value) {
            headers[col] = value;
            continue;
        }

        if(!data[row]) data[row]={};
        data[row][headers[col]] = value;
    }
    //drop those first two rows which are empty
    data.shift();
    data.shift();
    console.log(data);
});

答案 2 :(得分:29)

我认为这段代码会做你想要的。它将第一行存储为一组标头,然后将其余存储在一个数据对象中,您可以将其作为JSON写入磁盘。

var XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx');
var sheet_name_list = workbook.SheetNames;
sheet_name_list.forEach(function(y) {
    var worksheet = workbook.Sheets[y];
    var headers = {};
    var data = [];
    for(z in worksheet) {
        if(z[0] === '!') continue;
        //parse out the column, row, and value
        var col = z.substring(0,1);
        var row = parseInt(z.substring(1));
        var value = worksheet[z].v;

        //store header names
        if(row == 1) {
            headers[col] = value;
            continue;
        }

        if(!data[row]) data[row]={};
        data[row][headers[col]] = value;
    }
    //drop those first two rows which are empty
    data.shift();
    data.shift();
    console.log(data);
});

打印出来

[ { id: 1,
    headline: 'team: sally pearson',
    location: 'Australia',
    'body text': 'majority have…',
    media: 'http://www.youtube.com/foo' },
  { id: 2,
    headline: 'Team: rebecca',
    location: 'Brazil',
    'body text': 'it is a long established…',
    media: 'http://s2.image.foo/' } ]

答案 3 :(得分:3)

**podria ser algo asi en react y electron**

 xslToJson = workbook => {
        //var data = [];
        var sheet_name_list = workbook.SheetNames[0];
        return XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list], {
            raw: false,
            dateNF: "DD-MMM-YYYY",
            header:1,
            defval: ""
        });
    };

    handleFile = (file /*:File*/) => {
        /* Boilerplate to set up FileReader */
        const reader = new FileReader();
        const rABS = !!reader.readAsBinaryString;

        reader.onload = e => {
            /* Parse data */
            const bstr = e.target.result;
            const wb = XLSX.read(bstr, { type: rABS ? "binary" : "array" });
            /* Get first worksheet */
            let arr = this.xslToJson(wb);

            console.log("arr ", arr)
            var dataNueva = []

            arr.forEach(data => {
                console.log("data renaes ", data)
            })
            // this.setState({ DataEESSsend: dataNueva })
            console.log("dataNueva ", dataNueva)

        };


        if (rABS) reader.readAsBinaryString(file);
        else reader.readAsArrayBuffer(file);
    };

    handleChange = e => {
        const files = e.target.files;
        if (files && files[0]) {
            this.handleFile(files[0]);
        }
    };

答案 4 :(得分:1)

对于那些在接受的答案中为yztt苦苦挣扎的人,这里有一个五边形的方法版本,其语法没有简化。用法:parseXlsx().subscribe((data)=> {...})

parseXlsx() {
    let self = this;
    return Observable.create(observer => {
        this.http.get('./assets/input.xlsx', { responseType: 'arraybuffer' }).subscribe((data: ArrayBuffer) => {
            const XLSX = require('xlsx');
            let file = new Uint8Array(data);
            let workbook = XLSX.read(file, { type: 'array' });
            let sheetNamesList = workbook.SheetNames;

            let allLists = {};
            sheetNamesList.forEach(function (sheetName) {
                let worksheet = workbook.Sheets[sheetName];
                let currentWorksheetHeaders: object = {};
                let data: Array<any> = [];
                for (let cellName in worksheet) {//cellNames example: !ref,!margins,A1,B1,C1

                    //skipping serviceCells !margins,!ref
                    if (cellName[0] === '!') {
                        continue
                    };

                    //parse colName, rowNumber, and getting cellValue
                    let numberPosition = self.getCellNumberPosition(cellName);
                    let colName = cellName.substring(0, numberPosition);
                    let rowNumber = parseInt(cellName.substring(numberPosition));
                    let cellValue = worksheet[cellName].w;// .w is XLSX property of parsed worksheet

                    //treating '-' cells as empty on Spot Indices worksheet
                    if (cellValue.trim() == "-") {
                        continue;
                    }

                    //storing header column names
                    if (rowNumber == 1 && cellValue) {
                        currentWorksheetHeaders[colName] = typeof (cellValue) == "string" ? cellValue.toCamelCase() : cellValue;
                        continue;
                    }

                    //creating empty object placeholder to store current row
                    if (!data[rowNumber]) {
                        data[rowNumber] = {}
                    };

                    //if header is date - for spot indices headers are dates
                    data[rowNumber][currentWorksheetHeaders[colName]] = cellValue;

                }

                //dropping first two empty rows
                data.shift();
                data.shift();
                allLists[sheetName.toCamelCase()] = data;
            });

            this.parsed = allLists;

            observer.next(allLists);
            observer.complete();
        })
    });
}

答案 5 :(得分:0)

我找到了一种更好的方法

  function genrateJSONEngine() {
    var XLSX = require('xlsx');
    var workbook = XLSX.readFile('test.xlsx');
    var sheet_name_list = workbook.SheetNames;
    sheet_name_list.forEach(function (y) {
      var array = workbook.Sheets[y];

      var first = array[0].join()
      var headers = first.split(',');

      var jsonData = [];
      for (var i = 1, length = array.length; i < length; i++) {

        var myRow = array[i].join();
        var row = myRow.split(',');

        var data = {};
        for (var x = 0; x < row.length; x++) {
          data[headers[x]] = row[x];
        }
        jsonData.push(data);

      }

答案 6 :(得分:0)

这是我使用一些 ramdas 助手的解决方案(在打字稿中)。它支持多个工作表,并返回一个以键为工作表名称的对象。

const parseXLSX = (file: File, cb: callback) => {
  const reader = new FileReader()
  const rABS = !!reader.readAsBinaryString

  reader.onload = (e) => {
    const bstr = e?.target?.result
    const wb = XLSX.read(bstr, { type: rABS ? 'binary' : 'array' })
    const sheetNames = wb.SheetNames
    const sheetsData = sheetNames.reduce((acc, sheetName) => {
      const worksheet = wb.Sheets[sheetName]
      const headers: Record<string, string> = {}
      const data: Record<string, unknown>[] = []

      keys(worksheet).forEach((key) => {
        // removes !ref column
        if (String(key)?.[0] !== '!') {
          // supports wide tables ex: AA1
          const column = String(key).replace(/[0-9]/g, '')
          const row = parseInt(String(key).replace(/\D/g, ''), 10)
          const value = worksheet[key].v

          if (row === 1) {
            headers[column] = value
          }

          // this solution does not support when header is not first row
          if (headers[column] !== undefined) {
            if (!data[row]) {
              data[row] = {}
            }

            data[row][headers[column]] = value
          }
        }
      })

      return {
        ...acc,
        [sheetName]: drop(1, data.filter(Boolean)),
      }
    }, {})

    cb(sheetsData)
  }
  if (rABS) reader.readAsBinaryString(file)
  else reader.readAsArrayBuffer(file)
}