NativeScript 中的原生工作表
NativeScript 是一个移动应用框架。它构建使用 JavaScript 来描述布局和事件的 iOS 和 Android 应用。
¥NativeScript 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.
该演示使用 NativeScript 和 SheetJS 来处理和生成电子表格。我们将探讨如何在 NativeScript 应用中加载 SheetJS;解析并生成存储在设备上的电子表格;并获取和解析远程文件。
¥This demo uses NativeScript and SheetJS to process and generate spreadsheets. We'll explore how to load SheetJS in a NativeScript app; parse and generate spreadsheets stored on the device; and fetch and parse remote files.
"完整示例" 创建一个应用,如下图所示:
¥The "Complete Example" creates an app that looks like the screenshots below:
iOS | Android |
---|---|
讨论内容涵盖 NativeScript + Angular 集成。假定熟悉 Angular 和 TypeScript。
¥The discussion covers the NativeScript + Angular integration. Familiarity with Angular and TypeScript is assumed.
本 demo 在以下环境下进行了测试:
¥This demo was tested in the following environments:
真实设 备
¥Real Devices
OS | 设备 | NS | 日期 |
---|---|---|---|
安卓 30 | 英伟达盾 | 8.9.2 | 2025-05-06 |
iOS 15.1 | iPad Pro | 8.9.2 | 2025-05-06 |
模拟器
¥Simulators
OS | 设备 | NS | 开发平台 | 日期 |
---|---|---|---|---|
Android 35 | Pixel 9 Pro XL | 8.9.2 | darwin-x64 | 2025-05-06 |
iOS 18.4 | iPhone 16 Pro Max | 8.9.2 | darwin-x64 | 2025-05-06 |
Android 35 | Pixel 9 | 8.9.2 | win11-x64 | 2025-06-08 |
Android 35 | Pixel 9 | 8.8.3 | linux-x64 | 2025-01-02 |
在开始此演示之前,请手动禁用遥测。
¥Before starting this demo, manually disable telemetry.
NativeScript 8.6.1 将遥测分为两部分:"usage" 和 "error"。两者都必须单独禁用:
¥NativeScript 8.6.1 split the telemetry into two parts: "usage" and "error". Both must be disabled separately:
npx -y -p nativescript ns usage-reporting disable
npx -y -p nativescript ns error-reporting disable
要验证遥测是否已禁用:
¥To verify telemetry was disabled:
npx -y -p nativescript ns usage-reporting status
npx -y -p nativescript ns error-reporting status
集成详情
¥Integration Details
SheetJS NodeJS 模块 可以从应用中的任何组件或脚本导入。
¥The SheetJS NodeJS Module can be imported from any component or script in the app.
@nativescript/core/file-system
包提供了用于文件访问的类。File
类不支持二进制数据,但 @nativescript/core
的文件访问单例支持读写 ArrayBuffer
数据。
¥The @nativescript/core/file-system
package provides classes for file access.
The File
class does not support binary data, but the file access singleton
from @nativescript/core
does support reading and writing ArrayBuffer
data.
读取和写入数据需要 URL。以下代码片段在典型文档文件夹中搜索指定的文件名:
¥Reading and writing data require a URL. The following snippet searches typical document folders for a specified filename:
import { Folder, knownFolders, path } from '@nativescript/core/file-system';
function get_url_for_filename(filename: string): string {
const target: Folder = knownFolders.documents() || knownFolders.ios.sharedPublic();
return path.normalize(target.path + "///" + filename);
}
应用配置
¥App Configuration
出于隐私考虑,应用必须请求文件访问权限。有用于访问数据的特殊 API,并且在未来的平台版本中可能会发生变化。
¥Due to privacy concerns, apps must request file access. There are special APIs for accessing data and are subject to change in future platform versions.
Technical Details (click to show)
iOS
The following key/value pairs must be added to Info.plist
:
<dict>
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
Android
Android security has evolved over the years. In newer Android versions, the following workarounds were required:
READ_EXTERNAL_STORAGE
andWRITE_EXTERNAL_STORAGE
allow apps to access files outside of the app scope. These are required for scoped storage access.
When the demo was last tested, this option was enabled by default.
android:requestLegacyExternalStorage="true"
enabled legacy behavior in some older releases.
The manifest is saved to App_Resources/Android/src/main/AndroidManifest.xml
:
<application
android:requestLegacyExternalStorage="true"
android:name="com.tns.NativeScriptApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:hardwareAccelerated="true">
- Permissions must be explicitly requested.
@nativescript-community/perms
is a community module for managing permissions:
import { request } from '@nativescript-community/perms';
import { File } from '@nativescript/core/file-system';
Storage access must be requested before writing data:
/* request permissions */
const res = await request('storage');
The external paths can be resolved using the low-level APIs:
/* find Downloads folder */
const dl_dir = android.os.Environment.DIRECTORY_DOWNLOADS;
const dl = android.os.Environment.getExternalStoragePublicDirectory(dl_dir).getAbsolutePath();
/* write to file */
File.fromPath(dl + "/SheetJSNS.xls").writeSync(data);
读取本地文件
¥Reading Local Files
getFileAccess().readBufferAsync
可以将数据读入 ArrayBuffer
对象。SheetJS read
方法 [^1] 可以将此数据解析为工作簿对象。[^2]
¥getFileAccess().readBufferAsync
can read data into an ArrayBuffer
object.
The SheetJS read
method[^1] can parse this data into a workbook object.[^2]
import { getFileAccess } from '@nativescript/core';
import { read } from 'xlsx';
/* find appropriate path */
const url = get_url_for_filename("SheetJSNS.xls");
/* get data */
const ab: ArrayBuffer = await getFileAccess().readBufferAsync(url);
/* read workbook */
const wb = read(ab);
解析成工作簿后,sheet_to_json
[^3] 方法可以生成行数据对象:
¥After parsing into a workbook, the sheet_to_json
[^3] method can generate row
data objects:
import { utils } from 'xlsx';
/* grab first sheet */
const wsname: string = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* generate array of row objects */
const data = utils.sheet_to_json(ws);
写入本地文件
¥Writing Local Files
带有选项 type: "binary"
的 SheetJS write
方法 [^4] 将生成 Uint8Array
对象。getFileAccess().writeBufferAsync
可以将数据从 Uint8Array
对象写入设备。
¥The SheetJS write
method[^4] with the option type: "binary"
will generate
Uint8Array
objects. getFileAccess().writeBufferAsync
can write data from a
Uint8Array
object to the device.
iOS 直接支持 Uint8Array
,但 Android 需要一个真正的数字数组:
¥iOS supports Uint8Array
directly but Android requires a true array of numbers:
import { getFileAccess } from '@nativescript/core';
import { write } from 'xlsx';
/* find appropriate path */
const url = get_url_for_filename("SheetJSNS.xls");
/* generate Uint8Array */
const u8: Uint8Array = write(wb, { bookType: 'xls', type: 'binary' });
/* attempt to save Uint8Array to file */
await getFileAccess().writeBufferAsync(url, global.isAndroid ? (Array.from(u8) as any) : u8);
可以使用 SheetJS json_to_sheet
方法 [^5] 从行对象数组生成工作表。生成数组后,book_new
和 book_append_sheet
方法 [^6] 可以创建工作簿。
¥A worksheet can be generated from an array of row objects with the SheetJS
json_to_sheet
method[^5]. After generating an array, the book_new
and
book_append_sheet
methods[^6] can create the workbook.
获取远程文件
¥Fetching Remote Files
getFile
可以从 @nativescript/core/http
下载文件。将文件存储在临时文件夹中后,getFileAccess().readBufferAsync
可以读取数据,SheetJS read
方法 [^7] 可以解析该文件:
¥getFile
from @nativescript/core/http
can download files. After storing the
file in a temporary folder, getFileAccess().readBufferAsync
can read the data
and the SheetJS read
method[^7] can parse the file:
import { knownFolders, path, getFileAccess } from '@nativescript/core'
import { getFile } from '@nativescript/core/http';
import { read } from 'xlsx';
/* generate temporary path for the new file */
const temp: string = path.join(knownFolders.temp().path, "pres.xlsx");
/* download file */
const file = await getFile("https://xlsx.nodejs.cn/pres.xlsx", temp)
/* get data */
const ab: ArrayBuffer = await getFileAccess().readBufferAsync(file.path);
/* read workbook */
const wb = read(ab);
完整示例
¥Complete Example
平台配置
¥Platform Configuration
-
禁用遥测:
¥Disable telemetry:
npx -y -p nativescript ns usage-reporting disable
npx -y -p nativescript ns error-reporting disable
-
请遵循官方环境设置说明 [^8]。
¥Follow the official Environment Setup instructions[^8].
在之前的测试运行中,NativeScript 不支持最新的 Android API。npx -y -p nativescript ns doctor android
的错误消息清楚地说明了支持的版本:
¥In previous test runs, NativeScript did not support the latest Android API.
The error message from npx -y -p nativescript ns doctor android
clearly stated
supported versions:
✖ No compatible version of the Android SDK Build-tools are installed on your system. You can install any version in the following range: '>=23 <=33'.
如果 NativeScript 无法正确支持最新的 API 级别,则应使用 Android Studio 安装旧版本的 API。
¥If NativeScript does not properly support the latest API level, an older API version should be installed using Android Studio.
在之前的测试运行中,需要以下软件包:
¥In a previous test run, the following packages were required:
-
Android 13.0 ("Tiramisu")
API 级别33
¥
Android 13.0 ("Tiramisu")
API Level33
-
Android SDK Build-Tools
版本33.0.2
¥
Android SDK Build-Tools
Version33.0.2
建议安装 SDK 平台和相应的 Android SDK 构建工具,以支持最新支持的 API 级别。
¥It is recommended to install the SDK Platform and corresponding Android SDK Build-Tools for the latest supported API level.
-
测试 Android 开发的本地系统配置:
¥Test the local system configuration for Android development:
npx -y -p nativescript ns doctor android
在上次 macOS 测试中,显示了以下输出:
¥In the last macOS test, the following output was displayed:
Expected output (click to hide)
✔ Getting environment information
No issues were detected. ✔ Your ANDROID_HOME environment variable is set and points to correct directory. ✔ Your adb from the Android SDK is correctly installed. ✔ The Android SDK is installed. ✔ A compatible Android SDK for compilation is found. ✔ Javac is installed and is configured properly. ✔ The Java Development Kit (JDK) is installed and is configured properly. ✔ Getting NativeScript components versions information... ✔ Component nativescript has 8.9.2 version and is up to date.
-
测试 iOS 开发的本地系统配置(仅限 macOS):
¥Test the local system configuration for iOS development (macOS only):
npx -y -p nativescript ns doctor ios
在上次 macOS 测试中,显示了以下输出:
¥In the last macOS test, the following output was displayed:
Expected output (click to hide)
✔ Getting environment information
No issues were detected. ✔ Xcode is installed and is configured properly. ✔ xcodeproj is installed and is configured properly. ✔ CocoaPods are installed. ✔ CocoaPods update is not required. ✔ CocoaPods are configured properly. ✔ Your current CocoaPods version is newer than 1.0.0. ✔ Python installed and configured correctly. ✔ Xcode version 16.3.0 satisfies minimum required version 10. ✔ Getting NativeScript components versions information... ✔ Component nativescript has 8.9.2 version and is up to date.
基础项目
¥Base Project
-
创建一个 NativeScript + Angular 应用框架:
¥Create a skeleton NativeScript + Angular app:
npx -y -p nativescript ns create SheetJSNS --ng
-
在 Android 模拟器中启动应用以验证应用:
¥Launch the app in the Android simulator to verify the app:
cd SheetJSNS
npx -y -p nativescript ns run android
(可能还要等一下)
¥(this may take a while)
模拟器启动并显示测试应用后,选择终端并按 CTRL+C 结束脚本。在 Windows 上,如果提示输入 Terminate batch job
,请键入 Y 并按 Enter。