使用 React Native 随时随地使用表格
React Native 是一个移动应用框架。它构建使用 JavaScript 来描述布局和事件的 iOS 和 Android 应用。
¥React Native is a mobile app framework. It builds iOS and Android apps that use JavaScript for describing layouts and events.
SheetJS 是一个用于从电子表格读取和写入数据的 JavaScript 库。
¥SheetJS is a JavaScript library for reading and writing data from spreadsheets.
该演示使用 React Native 和 SheetJS 来处理和生成电子表格。我们将探讨如何通过几种方式在 React Native 应用中加载 SheetJS:
¥This demo uses React Native and SheetJS to process and generate spreadsheets. We'll explore how to load SheetJS in a React Native app in a few ways:
-
"获取远程数据" 使用内置的
fetch
下载并解析远程工作簿文件。¥"Fetching Remote Data" uses the built-in
fetch
to download and parse remote workbook files. -
"本地文件" 使用原生库在设备上读取和写入文件。
¥"Local Files" uses native libraries to read and write files on the device.
"本地文件" 示例创建了一个如下屏幕截图所示的应用:
¥The "Local Files" example creates an app that looks like the screenshots below:
iOS | Android |
---|---|
在测试此演示之前,请遵循官方 React Native CLI 指南![^1]
¥Before testing this demo, follow the official React Native CLI Guide![^1]
请按照 iOS(需要 macOS)和 Android 的说明进行操作。它们将涵盖安装和系统配置。你应该能够在 Android 和 iOS(如果适用)模拟器中构建并运行示例应用。
¥Follow the instructions for iOS (requires macOS) and for Android. They will cover installation and system configuration. You should be able to build and run a sample app in the Android and the iOS (if applicable) simulators.
集成详情
¥Integration Details
SheetJS NodeJS 模块 可以从应用中的任何组件或脚本导入。
¥The SheetJS NodeJS Module can be imported from any component or script in the app.
内部状态
¥Internal State
为简单起见,该演示使用 "数组的数组"[^2] 作为内部状态。
¥For simplicity, this demo uses an "Array of Arrays"[^2] as the internal state.
Spreadsheet | Array of Arrays |
---|---|
|
结构中的每个数组对应一行。
¥Each array within the structure corresponds to one row.
该演示还以单个数字数组的形式跟踪列宽。显示组件使用宽度。
¥This demo also keeps track of the column widths as a single array of numbers. The widths are used by the display component.
完整状态
¥Complete State
完整的状态使用以下代码片段进行初始化:
¥The complete state is initialized with the following snippet:
const [data, setData] = useState([
"SheetJS".split(""),
[5,4,3,3,7,9,5],
[8,6,7,5,3,0,9]
]);
const [widths, setWidths] = useState(Array.from({length:7}, () => 20));
更新状态
¥Updating State
从 SheetJS 工作表对象开始,带有 header
选项的 sheet_to_json
[^3] 可以生成数组的数组:
¥Starting from a SheetJS worksheet object, sheet_to_json
[^3] with the header
option can generate an array of arrays:
/* assuming `wb` is a SheetJS workbook */
function update_state(wb) {
/* convert first worksheet to AOA */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const data = utils.sheet_to_json(ws, {header:1});
/* update state */
setData(data);
/* update column widths */
setWidths(make_width(data));
}
计算列宽
¥Calculating Column Widths
可以通过遍历每列并计算最大数据宽度来计算列宽度。使用数组的数组:
¥Column widths can be calculated by walking each column and calculating the max data width. Using the array of arrays:
/* this function takes an array of arrays and generates widths */
function make_width(aoa) {
/* walk each row */
aoa.forEach((r) => {
/* walk each column */
r.forEach((c, C) => {
/* update column width based on the length of the cell contents */
res[C] = Math.max(res[C]||60, String(c).length * 10);
});
});
/* use a default value for columns with no data */
for(let C = 0; C < res.length; ++C) if(!res[C]) res[C] = 60;
return res;
}
导出状态
¥Exporting State
aoa_to_sheet
[^4] 从数组的数组构建一个 SheetJS 工作表对象:
¥aoa_to_sheet
[^4] builds a SheetJS worksheet object from the array of arrays:
/* generate a SheetJS workbook from the state */
function export_state() {
/* convert AOA back to worksheet */
const ws = utils.aoa_to_sheet(data);
/* build new workbook */
const wb = utils.book_new();
utils.book_append_sheet(wb, ws, "SheetJS");
return wb;
}