web-dev-qa-db-ja.com

XLSXファイルをJava

JavaアプリケーションでExcel 2007 XLSXファイルを読み取る必要があります。このタスクを実行するための優れたAPIを知っている人はいますか?

32
MrPortico

知る限り、xlsx-librariesはまだ利用できません。しかし、古いxlsにはいくつかあります:

1つのライブラリは jxls で、これは既に言及した [〜#〜] poi [〜#〜] を内部的に使用します。

他の2つのリンク: Excelファイルの処理Excel XLSドキュメントファイルを読み書きするJavaライブラリ

5
Tobias Schulte

Apache POI 3.5は、すべてのOOXML(docx、xlsxなど)のサポートを追加しました

XSSFサブプロジェクト を参照してください

50

.NETでこれを行う必要があり、そこにAPIが見つかりませんでした。私の解決策は、.xlsxを解凍し、XMLを操作することです。ヘルパークラスなどを作成したら、それほど悪くはありません。

Excelが期待する方法に従ってノードをすべてソートする必要があるような「落とし穴」がいくつかありますが、これは公式ドキュメントにはありませんでした。 Excelには独自の日付のタイムスタンプがあるため、変換式を作成する必要があります。

5
hova

少し遅れるかもしれませんが、ベータPOIは現在xlsxをサポートしています。

5
Galbrezu

これを試して:

  1. XLSXファイルを解凍します
  2. XMLファイルを読み取る
  3. データを作成して使用する

サンプルコード:

    public Workbook getTemplateData(String xlsxFile) {
    Workbook workbook = new Workbook();
    parseSharedStrings(xlsxFile);
    parseWorkesheet(xlsxFile, workbook);
    parseComments(xlsxFile, workbook);
    for (Worksheet worksheet : workbook.sheets) {
        worksheet.dimension = manager.getDimension(worksheet);
    }

    return workbook;
}

private void parseComments(String tmpFile, Workbook workbook) {
    try {
        FileInputStream fin = new FileInputStream(tmpFile);
        final ZipInputStream zin = new ZipInputStream(fin);
        InputStream in = getInputStream(zin);
        while (true) {
            ZipEntry entry = zin.getNextEntry();
            if (entry == null)
                break;

            String name = entry.getName();
            if (name.endsWith(".xml")) { //$NON-NLS-1$
                if (name.contains(COMMENTS)) {
                    parseComments(in, workbook);
                }
            }
            zin.closeEntry();
        }
        in.close();
        zin.close();
        fin.close();
    } catch (FileNotFoundException e) {
        System.out.println(e);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void parseComments(InputStream in, Workbook workbook) {
    try {
        DefaultHandler handler = getCommentHandler(workbook);
        SAXParser saxParser = getSAXParser();
        saxParser.parse(in, handler);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private DefaultHandler getCommentHandler(Workbook workbook) {
    final Worksheet ws = workbook.sheets.get(0);
    return new DefaultHandler() {
        String lastTag = "";
        private Cell ccell;

        @Override
        public void startElement(String uri, String localName,
                String qName, Attributes attributes) throws SAXException {
            lastTag = qName;
            if (lastTag.equals("comment")) {
                String cellName = attributes.getValue("ref");
                int r = manager.getRowIndex(cellName);
                int c = manager.getColumnIndex(cellName);
                Row row = ws.rows.get(r);
                if (row == null) {
                    row = new Row();
                    row.index = r;
                    ws.rows.put(r, row);
                }
                ccell = row.cells.get(c);
                if (ccell == null) {
                    ccell = new Cell();
                    ccell.cellName = cellName;
                    row.cells.put(c, ccell);
                }
            }
        }

        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            String val = "";
            if (ccell != null && lastTag.equals("t")) {
                for (int i = start; i < start + length; i++) {
                    val += ch[i];
                }
                if (ccell.comment == null)
                    ccell.comment = val;
                else {
                    ccell.comment += val;
                }
            }
        }
    };
}

private void parseSharedStrings(String tmpFile) {
    try {
        FileInputStream fin = new FileInputStream(tmpFile);
        final ZipInputStream zin = new ZipInputStream(fin);
        InputStream in = getInputStream(zin);
        while (true) {
            ZipEntry entry = zin.getNextEntry();
            if (entry == null)
                break;
            String name = entry.getName();
            if (name.endsWith(".xml")) { //$NON-NLS-1$
                if (name.startsWith(SHARED_STRINGS)) {
                    parseStrings(in);
                }
            }
            zin.closeEntry();
        }
        in.close();
        zin.close();
        fin.close();
    } catch (FileNotFoundException e) {
        System.out.println(e);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void parseWorkesheet(String tmpFile, Workbook workbook) {
    try {
        FileInputStream fin = new FileInputStream(tmpFile);
        final ZipInputStream zin = new ZipInputStream(fin);
        InputStream in = getInputStream(zin);
        while (true) {
            ZipEntry entry = zin.getNextEntry();
            if (entry == null)
                break;

            String name = entry.getName();
            if (name.endsWith(".xml")) { //$NON-NLS-1$
                if (name.contains("worksheets")) {
                    Worksheet worksheet = new Worksheet();
                    worksheet.name = name;
                    parseWorksheet(in, worksheet);
                    workbook.sheets.add(worksheet);
                }
            }
            zin.closeEntry();
        }
        in.close();
        zin.close();
        fin.close();
    } catch (FileNotFoundException e) {
        System.out.println(e);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void parseWorksheet(InputStream in, Worksheet worksheet)
        throws IOException {
    // read sheet1 sharedStrings
    // styles, strings, formulas ...
    try {
        DefaultHandler handler = getDefaultHandler(worksheet);
        SAXParser saxParser = getSAXParser();
        saxParser.parse(in, handler);
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    }
}

workbookクラス:

public class Workbook {
Integer id = null;
public List<Worksheet> sheets = new ArrayList<Worksheet>();}

およびWorksheetクラス:

public class Worksheet {
public Integer id = null;
public String name = null;
public String dimension = null;
public Map<Integer, Row> rows = new TreeMap<Integer, Row>();
public Map<Integer, Column> columns = new TreeMap<Integer, Column>();
public List<Span> spans = new ArrayList<Span>();}

および行クラス:

public class Row {
public Integer id = null;
public Integer index = null;
public Row tmpRow = null;
public Style style = null;
public Double height = null;
public Map<Integer,Cell> cells = new TreeMap<Integer, Cell>();
public String spans = null;
public Integer customHeight = null;}

およびCellクラス:

public class Cell {
public Integer id = null;
public Integer rowIndex = null;
public Integer colIndex = null;
public String cellName = null;
public String text = null;
public String formula = null;
public String comment = null;
public Style style = null;
public Object value = null;
public Cell tmpCell = null;}

およびColumnクラス:

public class Column {
    public Integer index = null;
    public Style style = null;
    public String width = null;
    public Column tmpColumn = null;
}

およびSpanクラス:

public class Span {
    Integer id = null;
    String topLeft = null;
    String bottomRight = null;
}
5
Koss

これは多分あなたのために働く、それはExcel 2007のxlsxファイルを読み書きすることができます。 SmartXLS

3
rya

どのオプションにもあまり満足していないので、最終的にExcel 97の形式でファイルを要求しました。 POIはそのために最適です。助けてくれてありがとう。

2
MrPortico

あまり難読化されていないAPI を見ましたか?

気にしないで:

HSSFは、POIプロジェクトの純粋なJava Excel '97(-2007)ファイル形式の実装です。OLE2ベースではない新しいExcel 2007 .xlsx OOXMLファイル形式をサポートしていません。

代わりに JDBC-ODBCブリッジ を使用することを検討してください。

1
Josh

Aspose.Cells for Java はXLSX形式をサポートします。詳細については、 Aspose.Cells for Java Documentation を参照してください。これが役立つかどうかを確認してください。

開示:Asposeで開発者エバンジェリストとして働いています。

1
Shahzad Latif

Excel 2007が最新かどうかはわかりませんが、以前のバージョンでは JExcelAPI を使用しています

1
NR.

docx4jは、xlsxもカバーするようになりました。

「なぜdocx4jを使用してこれを行うのですか」と聞いたのですが、「xlsxとバイナリxlsに焦点を当てたPOIではなく」

おそらく、XML Beanとは対照的にJAXBが好きか、docxまたはpptxにすでにdocx4jを使用していて、xlsxでも何かできるようにする必要があるからでしょう。

別の考えられる理由は、OpenXMLスキーマから生成されるjar XML Beansが目的に対して大きすぎることです。 (これを回避するために、POIは 'lite'サブセットを提供します: 'big' ooxml-schemas-1.0.jarは14.5 MBです!しかし、任意のスプレッドシートをサポートする必要がある場合は、おそらく完全なjarが必要です)。対照的に、docx4j/pptx4j/xlsx4j全体は、POIのライトサブセットとほぼ同じ重量になります。

スプレッドシートのみを処理する場合(つまり、docxまたはpptxを使用しない場合)、前の段落を気にしない場合は、おそらくPOIを使用するのが最善です。

1
JasonPlutext

Apache Tika を使用できます:

String parse(File xlsxFile) {
    return new Tika().parseToString(xlsxFile);
}

Tikaは、XLSXファイルの解析に Apache POI を使用します。

以下に、Tikiの 使用例 を示します。

または、スプレッドシートの各セルを個別に処理する場合は、POIでこれを行う1つの方法があります。

void parse(File xlsx) {
    try (XSSFWorkbook workbook = new XSSFWorkbook(xlsx)) {
        // Handle each cell in each sheet
        workbook.forEach(sheet -> sheet.forEach(row -> row.forEach(this::handle)));
    }
    catch (InvalidFormatException | IOException e) {
        System.out.println("Can't parse file " + xlsx);
    }
}

void handle(Cell cell) {
    final String cellContent;
    switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            cellContent = cell.getStringCellValue();
            break;
        case Cell.CELL_TYPE_NUMERIC:
            cellContent = String.valueOf(cell.getNumericCellValue());
            break;
        case Cell.CELL_TYPE_BOOLEAN:
            cellContent = String.valueOf(cell.getBooleanCellValue());
            break;
        default:
            cellContent = "Don't know how to handle cell " + cell;
    }
    System.out.println(cellContent);
}
1
Matthias Braun

Xlsxを使用する場合は、org.Apache.poi.ssパッケージを使用する必要があります。このパッケージにはクラスXSSFがあり、xlxsファイルの解析に使用できます。このサンプルコードは、Excel 2007以降(.xlsx)で動作します

OPCPackage pkg = OPCPackage.open(new ByteArrayInputStream(data));
            Workbook wb = new XSSFWorkbook(pkg);
            Sheet sheet = wb.getSheetAt(0);
            Iterator<Row> rows = sheet.rowIterator();

        while (rows.hasNext()) {
            int j = 5;
            Person person= new Person ();
            Row row = rows.next();
            if (row.getRowNum() > 0) {
                person.setPersonId((int)(row.getCell(0).getNumericCellValue()));
                person.setFirstName(row.getCell(1).getStringCellValue());
                person.setLastName(row.getCell(2).getStringCellValue());
                person.setGroupId((int)(row.getCell(3).getNumericCellValue()));
                person.setUserName(row.getCell(4).getStringCellValue());
                person.setCreditId((int)(row.getCell(5).getNumericCellValue()));
            }

        }

Excel 1998-2003 file (.xls) - you may use HSSF library.
  just use :  Workbook wb = new HSSFWorkbook(pkg);
0
patidarsnju