[英]How to create and write to Excel file (.xlsx)?
Java 開發人員的庫中有大量在 Android 上不起作用的方法。
我從使用 OpenCSV 之類的庫開始,但不幸的是 Excel 在打開 CSV 文件時存在已知問題。
然后我嘗試使用:
我的問題是,如何在 Android 上創建一個簡單的 .xlsx 格式的 Excel 文件,而不超過 65k 方法?
第一個答案:在服務器端做。
如果這不可能,只需使用 JExecelAPI - 幾乎所有讀取 xlsx 文件的東西也都會讀取 xls 文件。
其他所有 Excel 庫都會變得太大。
另一個想法 - 手動或使用許多可用的 csv 庫之一編寫 csv 文件。 同樣,大多數讀取 Excel 文件的應用程序也讀取 csv 文件。
由於這個問題似乎是:“為 Excel ( *.xlsx
) 創建 Office Open XML 文件的最輕量級方法是什么?”,我將提供一個示例,它不需要任何庫,除了默認的java.lang
, java.io
和java.util.zip
。
*.xlsx
文件只不過是包含 XML 文件和目錄結構中的其他文件的 ZIP 存檔。 因此,我們所需要的只是創建、讀取和寫入 ZIP 存檔以及創建、讀取和寫入 XML 文件的可能性。 對於 ZIP 部分,我使用java.util.zip
,對於 XML 部分,我使用字符串操作。 這種通過字符串操作創建和操作 XML 並不是最推薦的操作 XML 的方法,但它是最輕量級的方法,因為它不需要任何額外的 XML 庫。
完整示例:
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.*;
public class CreateXLSXFromScratch {
//some static parts of the XLSX file:
static String content_types_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" Extension=\"rels\"/><Default ContentType=\"application/xml\" Extension=\"xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.extended-properties+xml\" PartName=\"/docProps/app.xml\"/><Override ContentType=\"application/vnd.openxmlformats-package.core-properties+xml\" PartName=\"/docProps/core.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml\" PartName=\"/xl/sharedStrings.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\" PartName=\"/xl/styles.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\" PartName=\"/xl/workbook.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\" PartName=\"/xl/worksheets/sheet1.xml\"/></Types>";
static String docProps_app_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\"><Application>" + "Created Low level From Scratch" + "</Application></Properties>";
static String docProps_core_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><dcterms:created xsi:type=\"dcterms:W3CDTF\">" + java.time.Instant.now().truncatedTo(java.time.temporal.ChronoUnit.SECONDS).toString() + "</dcterms:created><dc:creator>" + "Axel Richter from scratch" + "</dc:creator></cp:coreProperties>";
static String _rels_rels_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Target=\"xl/workbook.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\"/><Relationship Id=\"rId2\" Target=\"docProps/app.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties\"/><Relationship Id=\"rId3\" Target=\"docProps/core.xml\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties\"/></Relationships>";
static String xl_rels_workbook_xml_rels_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Target=\"sharedStrings.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings\"/><Relationship Id=\"rId2\" Target=\"styles.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\"/><Relationship Id=\"rId3\" Target=\"worksheets/sheet1.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\"/></Relationships>";
static String xl_sharedstrings_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><sst count=\"0\" uniqueCount=\"0\" xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"/>";
static String xl_styles_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><numFmts count=\"0\"/><fonts count=\"1\"><font><sz val=\"11.0\"/><color indexed=\"8\"/><name val=\"Calibri\"/><family val=\"2\"/><scheme val=\"minor\"/></font></fonts><fills count=\"2\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"darkGray\"/></fill></fills><borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders><cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs><cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/></cellXfs></styleSheet>";
static String xl_workbook_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"><workbookPr date1904=\"false\"/><bookViews><workbookView activeTab=\"0\"/></bookViews><sheets><sheet name=\"" + "Sheet1" + "\" r:id=\"rId3\" sheetId=\"1\"/></sheets></workbook>";
static String xl_worksheets_sheet1_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><dimension ref=\"A1\"/><sheetViews><sheetView workbookViewId=\"0\" tabSelected=\"true\"/></sheetViews><sheetFormatPr defaultRowHeight=\"15.0\"/><sheetData/><pageMargins bottom=\"0.75\" footer=\"0.3\" header=\"0.3\" left=\"0.7\" right=\"0.7\" top=\"0.75\"/></worksheet>";
public static void main(String[] args) throws Exception {
// result goes into a ByteArrayOutputStream
ByteArrayOutputStream resultout = new ByteArrayOutputStream();
// needed objects
ZipEntry zipentry = null;
byte[] data = null;
// create ZipOutputStream
ZipOutputStream zipout = new ZipOutputStream(resultout);
// create the static parts of the XLSX ZIP file:
zipentry = new ZipEntry("[Content_Types].xml");
zipout.putNextEntry(zipentry);
data = content_types_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("docProps/app.xml");
zipout.putNextEntry(zipentry);
data = docProps_app_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("docProps/core.xml");
zipout.putNextEntry(zipentry);
data = docProps_core_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("_rels/.rels");
zipout.putNextEntry(zipentry);
data = _rels_rels_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/_rels/workbook.xml.rels");
zipout.putNextEntry(zipentry);
data = xl_rels_workbook_xml_rels_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/sharedStrings.xml");
zipout.putNextEntry(zipentry);
data = xl_sharedstrings_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/styles.xml");
zipout.putNextEntry(zipentry);
data = xl_styles_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/workbook.xml");
zipout.putNextEntry(zipentry);
data = xl_workbook_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
// preparing the sheet data:
Object[][] sheetData = new Object[][] {
{"Text", "Value", "Formula"},
{"Text1", 1.23456, "=SIN(B2)"},
{"Text2", 2.34567, "=SQRT(B3)"},
{"Text3", 123.456, "=B4/10"}
};
String sheetdata = "<sheetData>";
int r = 0;
char c = 'A'; --c;
for (Object[] rowData : sheetData) {
sheetdata += "<row r=\"" + ++r + "\">";
c = 'A'; --c;
for (Object cellData : rowData) {
sheetdata += "<c r=\"" + Character.toString(++c) + r + "\"";
if (cellData instanceof String && ((String)cellData).startsWith("=")) {
sheetdata += "><f>" + ((String)cellData).replace("=", "") + "</f></c>";
} else if (cellData instanceof String) {
sheetdata += " t=\"inlineStr\"><is><t>" + ((String)cellData) + "</t></is></c>";
} else if (cellData instanceof Double) {
sheetdata += "><v>" + ((Double)cellData) + "</v></c>";
}
}
sheetdata += "</row>";
}
sheetdata += "</sheetData>";
// get the static sheet xml into a buffer for further processing
StringBuffer xl_worksheets_sheet1_xml_buffer = new StringBuffer(xl_worksheets_sheet1_xml);
// get position of the <dimension ref=\"A1\"/> in the static xl_worksheets_sheet1_xml
int dimensionstart = xl_worksheets_sheet1_xml_buffer.indexOf("<dimension ref=\"A1\"/>");
// replace the <dimension ref=\"A1\"/> with the new dimension
xl_worksheets_sheet1_xml_buffer = xl_worksheets_sheet1_xml_buffer.replace(
dimensionstart,
dimensionstart + "<dimension ref=\"A1\"/>".length(),
"<dimension ref=\"A1:" + Character.toString(c) + r + "\"/>");
// get position of the <sheetData/> in the static xl_worksheets_sheet1_xml
int sheetdatastart = xl_worksheets_sheet1_xml_buffer.indexOf("<sheetData/>");
// replace the <sheetData/> with the prepared sheet date string
xl_worksheets_sheet1_xml_buffer = xl_worksheets_sheet1_xml_buffer.replace(
sheetdatastart,
sheetdatastart + "<sheetData/>".length(),
sheetdata);
// create the xl/worksheets/sheet1.xml
zipentry = new ZipEntry("xl/worksheets/sheet1.xml");
zipout.putNextEntry(zipentry);
data = xl_worksheets_sheet1_xml_buffer.toString().getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipout.finish();
// now ByteArrayOutputStream resultout contains the XLSX file data
// writing this data into a file
try (java.io.FileOutputStream fileout = new java.io.FileOutputStream("test.xlsx")) {
resultout.writeTo(fileout);
resultout.close();
}
}
}
現在是 2018 年。使用 Microsoft Graph API 並在 O365 中創建 Excel 文件。
Microsoft 已經發布了一些 Angular 和 C# 的示例。 它不是 Java,但它是一個很好的起點: https ://developer.microsoft.com/en-us/graph/docs/concepts/excel-write-to-workbook。
MS Graph Java SDK與 Android 兼容。
限制 - 沒有簡單的方法可以使用 API 從頭開始創建 Excel 文件。 您可能希望保留一個空白工作簿並每次都克隆它。
更新 Axel Richter 的回答:
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class CreatePlainXLSX {
//some static parts of the XLSX file:
static String content_types_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" Extension=\"rels\"/><Default ContentType=\"application/xml\" Extension=\"xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.extended-properties+xml\" PartName=\"/docProps/app.xml\"/><Override ContentType=\"application/vnd.openxmlformats-package.core-properties+xml\" PartName=\"/docProps/core.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml\" PartName=\"/xl/sharedStrings.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\" PartName=\"/xl/styles.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\" PartName=\"/xl/workbook.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\" PartName=\"/xl/worksheets/sheet1.xml\"/></Types>";
static String docProps_app_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\"><Application>" + "Created Low level From Scratch" + "</Application></Properties>";
static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
static String docProps_core_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><dcterms:created xsi:type=\"dcterms:W3CDTF\">" + formatter.format(Calendar.getInstance().getTime()) /*java.time.Instant.now().truncatedTo(java.time.temporal.ChronoUnit.SECONDS).toString()*/ + "</dcterms:created><dc:creator>" + "Axel Richter from scratch" + "</dc:creator></cp:coreProperties>";
static String _rels_rels_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Target=\"xl/workbook.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\"/><Relationship Id=\"rId2\" Target=\"docProps/app.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties\"/><Relationship Id=\"rId3\" Target=\"docProps/core.xml\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties\"/></Relationships>";
static String xl_rels_workbook_xml_rels_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Target=\"sharedStrings.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings\"/><Relationship Id=\"rId2\" Target=\"styles.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\"/><Relationship Id=\"rId3\" Target=\"worksheets/sheet1.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\"/></Relationships>";
static String xl_sharedstrings_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><sst count=\"0\" uniqueCount=\"0\" xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"/>";
static String xl_styles_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><numFmts count=\"0\"/><fonts count=\"1\"><font><sz val=\"11.0\"/><color indexed=\"8\"/><name val=\"Calibri\"/><family val=\"2\"/><scheme val=\"minor\"/></font></fonts><fills count=\"2\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"darkGray\"/></fill></fills><borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders><cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs><cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/></cellXfs></styleSheet>";
static String xl_workbook_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"><workbookPr date1904=\"false\"/><bookViews><workbookView activeTab=\"0\"/></bookViews><sheets><sheet name=\"" + "Sheet1" + "\" r:id=\"rId3\" sheetId=\"1\"/></sheets></workbook>";
static String xl_worksheets_sheet1_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><dimension ref=\"A1\"/><sheetViews><sheetView workbookViewId=\"0\" tabSelected=\"true\"/></sheetViews><sheetFormatPr defaultRowHeight=\"15.0\"/><sheetData/><pageMargins bottom=\"0.75\" footer=\"0.3\" header=\"0.3\" left=\"0.7\" right=\"0.7\" top=\"0.75\"/></worksheet>";
ArrayList<ArrayList<Object>> sheetDat = new ArrayList<>();
public CreatePlainXLSX() {
sheetDat.add(0, new ArrayList<>());
}
public void addCell(int rowNum, int cellNum, Object value) {
if (sheetDat.size() <= rowNum){
for (int a = sheetDat.size(); a <= rowNum; a++) {
sheetDat.add(new ArrayList<>());
}
}
if (sheetDat.get(rowNum).size() <= cellNum) {
for (int a = sheetDat.get(rowNum).size(); a <= cellNum; a++) {
sheetDat.get(rowNum).add("");
}
}
sheetDat.get(rowNum).set(cellNum, value);
}
private static int toNumber(String name) {
int number = 0;
for (int i = 0; i < name.length(); i++) {
number = number * 26 + (name.charAt(i) - ('A' - 1));
}
return number;
}
private static String toName(int number) {
StringBuilder sb = new StringBuilder();
while (number-- > 0) {
sb.append((char)('A' + (number % 26)));
number /= 26;
}
return sb.reverse().toString();
}
private String incrementColumnR(String a){
return toName(toNumber(a) + 1);
}
public void exportToFile(FileOutputStream fileout) throws Exception {
// result goes into a ByteArrayOutputStream
ByteArrayOutputStream resultout = new ByteArrayOutputStream();
// needed objects
ZipEntry zipentry;
byte[] data;
// create ZipOutputStream
ZipOutputStream zipout = new ZipOutputStream(resultout);
// create the static parts of the XLSX ZIP file:
zipentry = new ZipEntry("[Content_Types].xml");
zipout.putNextEntry(zipentry);
data = content_types_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("docProps/app.xml");
zipout.putNextEntry(zipentry);
data = docProps_app_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("docProps/core.xml");
zipout.putNextEntry(zipentry);
data = docProps_core_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("_rels/.rels");
zipout.putNextEntry(zipentry);
data = _rels_rels_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/_rels/workbook.xml.rels");
zipout.putNextEntry(zipentry);
data = xl_rels_workbook_xml_rels_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/sharedStrings.xml");
zipout.putNextEntry(zipentry);
data = xl_sharedstrings_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/styles.xml");
zipout.putNextEntry(zipentry);
data = xl_styles_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/workbook.xml");
zipout.putNextEntry(zipentry);
data = xl_workbook_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
// preparing the sheet data:
String sheetdata = "<sheetData>";
int r = 0;
String c = toName(0);
ArrayList<ArrayList<Object>> sheet = sheetDat;
for (ArrayList<Object> rowData : sheet) {
sheetdata += "<row r=\"" + ++r + "\">";
c = toName(0);
for (Object cellData : rowData) {
c = incrementColumnR(c);
sheetdata += "<c r=\"" + c + r + "\"";
if (cellData instanceof String && ((String) cellData).startsWith("=")) {
sheetdata += "><f>" + ((String) cellData).replace("=", "") + "</f></c>";
} else if (cellData instanceof String) {
sheetdata += " t=\"inlineStr\"><is><t>" + cellData + "</t></is></c>";
} else if (cellData instanceof Double || cellData instanceof Integer) {
sheetdata += "><v>" + cellData + "</v></c>";
}
}
sheetdata += "</row>";
}
sheetdata += "</sheetData>";
// get the static sheet xml into a buffer for further processing
StringBuffer xl_worksheets_sheet1_xml_buffer = new StringBuffer(xl_worksheets_sheet1_xml);
// get position of the <dimension ref=\"A1\"/> in the static xl_worksheets_sheet1_xml
int dimensionstart = xl_worksheets_sheet1_xml_buffer.indexOf("<dimension ref=\"A1\"/>");
// replace the <dimension ref=\"A1\"/> with the new dimension
xl_worksheets_sheet1_xml_buffer = xl_worksheets_sheet1_xml_buffer.replace(
dimensionstart,
dimensionstart + "<dimension ref=\"A1\"/>".length(),
"<dimension ref=\"A1:" + c + r + "\"/>");
// get position of the <sheetData/> in the static xl_worksheets_sheet1_xml
int sheetdatastart = xl_worksheets_sheet1_xml_buffer.indexOf("<sheetData/>");
// replace the <sheetData/> with the prepared sheet date string
xl_worksheets_sheet1_xml_buffer = xl_worksheets_sheet1_xml_buffer.replace(
sheetdatastart,
sheetdatastart + "<sheetData/>".length(),
sheetdata);
// create the xl/worksheets/sheet1.xml
zipentry = new ZipEntry("xl/worksheets/sheet1.xml");
zipout.putNextEntry(zipentry);
data = xl_worksheets_sheet1_xml_buffer.toString().getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipout.finish();
// now ByteArrayOutputStream resultout contains the XLSX file data
// writing this data into a file
if(fileout != null) {
resultout.writeTo(fileout);
resultout.close();
}
}
}
使用 Apache POI 並通過簡單地將compile "com.android.support:multidex:1.0.1"
添加到build.gradle
中的依賴項來啟用多 dex。 您還需要將 multiDexEnabled 設置為 true。 那應該擺脫 65k 方法的限制。
如果您不需要從任何來源讀取 xlsx 文件,我建議您使用 CSV excel 完全能夠將該類型轉換為其任何標准輸出。
即使您需要公式、單元格格式,也可以使用您引用的庫或使用您自己的 xml 解析器,正如我之前的許多人所說,excel 格式只是一個帶有 xml 的 zip。 這些xml在這里描述:
https://msdn.microsoft.com/en-us/library/dd979921(v=office.12).aspx
你會發現 excel 是一種非常復雜的格式,簡單的向后兼容並不是他們的首要任務。 因此,使用 XPath 或 JAXB 制作您自己的受限解析器將是一項繁重的工作,但並非不可能。
但我不明白你為什么要限制方法的數量? 如果它是關於制作一些嵌入式軟件,在我看來,你不應該使用.xlsx,這是一個復雜而沉重的文件,只是為了保存網格......
我正在擴展 Axel Richter 的回答我下面的代碼將為您添加動態添加列和值的功能。
導入android.os.Build;
導入androidx.annotation.RequiresApi;
導入 java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.zip.*;
@SuppressWarnings("WeakerAccess")
@RequiresApi(api = Build.VERSION_CODES.O)
public class ExcelSpreadSheet {
//some static parts of the XLSX file:
String content_types_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" Extension=\"rels\"/><Default ContentType=\"application/xml\" Extension=\"xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.extended-properties+xml\" PartName=\"/docProps/app.xml\"/><Override ContentType=\"application/vnd.openxmlformats-package.core-properties+xml\" PartName=\"/docProps/core.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml\" PartName=\"/xl/sharedStrings.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\" PartName=\"/xl/styles.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\" PartName=\"/xl/workbook.xml\"/><Override ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\" PartName=\"/xl/worksheets/sheet1.xml\"/></Types>";
String docProps_app_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\"><Application>" + "Created Low level From Scratch" + "</Application></Properties>";
String docProps_core_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><dcterms:created xsi:type=\"dcterms:W3CDTF\">" + java.time.Instant.now().truncatedTo(java.time.temporal.ChronoUnit.SECONDS).toString() + "</dcterms:created><dc:creator>" + "Axel Richter from scratch" + "</dc:creator></cp:coreProperties>";
String _rels_rels_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Target=\"xl/workbook.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\"/><Relationship Id=\"rId2\" Target=\"docProps/app.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties\"/><Relationship Id=\"rId3\" Target=\"docProps/core.xml\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties\"/></Relationships>";
String xl_rels_workbook_xml_rels_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Target=\"sharedStrings.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings\"/><Relationship Id=\"rId2\" Target=\"styles.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\"/><Relationship Id=\"rId3\" Target=\"worksheets/sheet1.xml\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\"/></Relationships>";
String xl_sharedstrings_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><sst count=\"0\" uniqueCount=\"0\" xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"/>";
String xl_styles_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><numFmts count=\"0\"/><fonts count=\"1\"><font><sz val=\"11.0\"/><color indexed=\"8\"/><name val=\"Calibri\"/><family val=\"2\"/><scheme val=\"minor\"/></font></fonts><fills count=\"2\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"darkGray\"/></fill></fills><borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders><cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs><cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/></cellXfs></styleSheet>";
String xl_workbook_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"><workbookPr date1904=\"false\"/><bookViews><workbookView activeTab=\"0\"/></bookViews><sheets><sheet name=\"" + "Sheet1" + "\" r:id=\"rId3\" sheetId=\"1\"/></sheets></workbook>";
String xl_worksheets_sheet1_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><dimension ref=\"A1\"/><sheetViews><sheetView workbookViewId=\"0\" tabSelected=\"true\"/></sheetViews><sheetFormatPr defaultRowHeight=\"15.0\"/><sheetData/><pageMargins bottom=\"0.75\" footer=\"0.3\" header=\"0.3\" left=\"0.7\" right=\"0.7\" top=\"0.75\"/></worksheet>";
ArrayList<ArrayList<Object>> sheetDat = new ArrayList<>();
ArrayList<Object> sheetKeys = new ArrayList<>();
ExcelSpreadSheet() {
sheetDat.add(0, new ArrayList<>());
}
int addFirstColumnKey(String key) {
if (!sheetKeys.contains(key)) {
if (sheetKeys.size() > 26) return -1;
sheetKeys.add(key);
}
return sheetKeys.indexOf(key);
}
void addValueToRow(int rowID, String keyName, Object value) {
addFirstColumnKey("ID");
int columnEdit = addFirstColumnKey(keyName);
if (columnEdit == -1) return;//ERROR
int editingRow = -1;
for (int i = 0; i < sheetDat.size(); i++) {
if (sheetDat.get(i).get(0).equals(rowID)) {
editingRow = i;
}
}
if (editingRow == -1) {
sheetDat.add(new ArrayList<>());
editingRow = sheetDat.size() - 1;
}
if (sheetDat.get(editingRow).size() < sheetKeys.size()) {
for (int a = 0; a < sheetKeys.size(); a++) {
sheetDat.get(editingRow).add(0);
}
}
sheetDat.get(editingRow).set(columnEdit, value);
sheetDat.get(editingRow).set(0, rowID);
}
private class Sort implements Comparator<ArrayList<Object>> {
int sortColumn;
Sort(int columnToSortBy) {
sortColumn = columnToSortBy;
}
public int compare(ArrayList<Object> a, ArrayList<Object> b) {
if (a.size() < sortColumn || a.get(sortColumn) == null) {
return 0;
} else if (a.get(sortColumn) instanceof String) {
return ((String) a.get(sortColumn)).compareTo(((String) b.get(sortColumn)));
} else if (a.get(sortColumn) instanceof Integer) {
return ((Integer) a.get(sortColumn)).compareTo(((Integer) b.get(sortColumn)));
} else if (a.get(sortColumn) instanceof Long) {
return ((Long) a.get(sortColumn)).compareTo(((Long) b.get(sortColumn)));
} else if (a.get(sortColumn) instanceof Double) {
return ((Double) a.get(sortColumn)).compareTo(((Double) b.get(sortColumn)));
}
return 0;
}
}
void exportToFile() throws Exception {
// result goes into a ByteArrayOutputStream
ByteArrayOutputStream resultout = new ByteArrayOutputStream();
// needed objects
ZipEntry zipentry;
byte[] data;
// create ZipOutputStream
ZipOutputStream zipout = new ZipOutputStream(resultout);
// create the static parts of the XLSX ZIP file:
zipentry = new ZipEntry("[Content_Types].xml");
zipout.putNextEntry(zipentry);
data = content_types_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("docProps/app.xml");
zipout.putNextEntry(zipentry);
data = docProps_app_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("docProps/core.xml");
zipout.putNextEntry(zipentry);
data = docProps_core_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("_rels/.rels");
zipout.putNextEntry(zipentry);
data = _rels_rels_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/_rels/workbook.xml.rels");
zipout.putNextEntry(zipentry);
data = xl_rels_workbook_xml_rels_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/sharedStrings.xml");
zipout.putNextEntry(zipentry);
data = xl_sharedstrings_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/styles.xml");
zipout.putNextEntry(zipentry);
data = xl_styles_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipentry = new ZipEntry("xl/workbook.xml");
zipout.putNextEntry(zipentry);
data = xl_workbook_xml.getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
// preparing the sheet data:
String sheetdata = "<sheetData>";
int r = 0;
char c = 'A';
--c;
ArrayList<ArrayList<Object>> sheet = sheetDat;
sheet.add(0, sheetKeys);
for (ArrayList<Object> rowData : sheet) {
sheetdata += "<row r=\"" + ++r + "\">";
c = 'A';
--c;
for (Object cellData : rowData) {
sheetdata += "<c r=\"" + Character.toString(++c) + r + "\"";
if (cellData instanceof String && ((String) cellData).startsWith("=")) {
sheetdata += "><f>" + ((String) cellData).replace("=", "") + "</f></c>";
} else if (cellData instanceof String) {
sheetdata += " t=\"inlineStr\"><is><t>" + cellData + "</t></is></c>";
} else if (cellData instanceof Double) {
sheetdata += "><v>" + cellData + "</v></c>";
}
}
sheetdata += "</row>";
}
sheetdata += "</sheetData>";
// get the static sheet xml into a buffer for further processing
StringBuffer xl_worksheets_sheet1_xml_buffer = new StringBuffer(xl_worksheets_sheet1_xml);
// get position of the <dimension ref=\"A1\"/> in the static xl_worksheets_sheet1_xml
int dimensionstart = xl_worksheets_sheet1_xml_buffer.indexOf("<dimension ref=\"A1\"/>");
// replace the <dimension ref=\"A1\"/> with the new dimension
xl_worksheets_sheet1_xml_buffer = xl_worksheets_sheet1_xml_buffer.replace(
dimensionstart,
dimensionstart + "<dimension ref=\"A1\"/>".length(),
"<dimension ref=\"A1:" + c + r + "\"/>");
// get position of the <sheetData/> in the static xl_worksheets_sheet1_xml
int sheetdatastart = xl_worksheets_sheet1_xml_buffer.indexOf("<sheetData/>");
// replace the <sheetData/> with the prepared sheet date string
xl_worksheets_sheet1_xml_buffer = xl_worksheets_sheet1_xml_buffer.replace(
sheetdatastart,
sheetdatastart + "<sheetData/>".length(),
sheetdata);
// create the xl/worksheets/sheet1.xml
zipentry = new ZipEntry("xl/worksheets/sheet1.xml");
zipout.putNextEntry(zipentry);
data = xl_worksheets_sheet1_xml_buffer.toString().getBytes();
zipout.write(data, 0, data.length);
zipout.closeEntry();
zipout.finish();
// now ByteArrayOutputStream resultout contains the XLSX file data
// writing this data into a file
try (java.io.FileOutputStream fileout = new java.io.FileOutputStream("working.xlsx")) {
resultout.writeTo(fileout);
resultout.close();
}
}
}
或者,如果您需要手動添加值,直到行 AZ,請更改 Axel Richter 答案的這一部分:
從
String sheetdata = "<sheetData>";
int r = 0;
String c = toName(0);
ArrayList<ArrayList<Object>> sheet = sheetDat;
for (ArrayList<Object> rowData : sheet) {
sheetdata += "<row r=\"" + ++r + "\">";
c = toName(0);
for (Object cellData : rowData) {
c = incrementColumnR(c);
sheetdata += "<c r=\"" + c + r + "\"";
if (cellData instanceof String && ((String) cellData).startsWith("=")) {
sheetdata += "><f>" + ((String) cellData).replace("=", "") + "</f></c>";
} else if (cellData instanceof String) {
sheetdata += " t=\"inlineStr\"><is><t>" + cellData + "</t></is></c>";
} else if (cellData instanceof Double || cellData instanceof Integer) {
sheetdata += "><v>" + cellData + "</v></c>";
}
}
sheetdata += "</row>";
}
sheetdata += "</sheetData>";
至
String sheetdata = "<sheetData>";
int column = 0;
int r = 0;
char c = 'A';
--c;
for (Object[] rowData : sheetData) {
sheetdata += "<row r=\"" + ++r + "\">";
column = 0;
c = 'A';
--c;
for (Object cellData : rowData) {
if (column > 25 || ((Character.isLetter(c) && Character.isUpperCase(c)) || c == '@')) {
if (column > 25) {
if (column == 26) {
c = 'A';
--c;
}
sheetdata += "<c r=\"" + "A" + Character.toString(++c) + r + "\"";
} else if ((Character.isLetter(c) && Character.isUpperCase(c)) || c == '@') {
sheetdata += "<c r=\"" + Character.toString(++c) + r + "\"";
}
column++;
if (cellData instanceof String && ((String) cellData).startsWith("=")) {
sheetdata += "><f>" + ((String) cellData).replace("=", "") + "</f></c>";
} else if (cellData instanceof String) {
sheetdata += " t=\"inlineStr\"><is><t>" + ((String) cellData) + "</t></is></c>";
} else if (cellData instanceof Double) {
sheetdata += "><v>" + ((Double) cellData) + "</v></c>";
}
}
}
sheetdata += "</row>";
}
xlsx 是一個壓縮文件。 因此,我們可以提取 zip 並獲取其中的 xml 文件,然后我們可以自己解析它以獲取工作表數據。
這應該適用於 xls 和 xlsx。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.