Skip to main content

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:

iOSAndroid

iOS screenshot

Android screenshot

讨论内容涵盖 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.7.22024-06-09
iOS 15.1iPad Pro8.7.22024-06-09

模拟器

¥Simulators

OS设备NS开发平台日期
安卓 34像素 3a8.7.2darwin-arm2024-06-09
iOS 17.5iPhone SE(第 3 代)8.7.2darwin-arm2024-06-09
安卓 34像素 3a8.6.5win10-x642024-04-07
遥测

在开始此演示之前,请手动禁用遥测。

¥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 -p nativescript ns usage-reporting disable
npx -p nativescript ns error-reporting disable

要验证遥测是否已禁用:

¥To verify telemetry was disabled:

npx -p nativescript ns usage-reporting status
npx -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)

Android

Android security has evolved over the years. In newer Android versions, the following workarounds were required:

  • READ_EXTERNAL_STORAGE and WRITE_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:

App_Resources/Android/src/main/AndroidManifest.xml (add highlighted lines)
  <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:

App script or component
import { request } from '@nativescript-community/perms';
import { File } from '@nativescript/core/file-system';

Storage access must be requested before writing data:

App script or component (before writing file)
  /* request permissions */
const res = await request('storage');

The external paths can be resolved using the low-level APIs:

App script or component (writing to downloads folder)
  /* 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_newbook_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

  1. 禁用遥测:

    ¥Disable telemetry:

npx -p nativescript ns usage-reporting disable
npx -p nativescript ns error-reporting disable
  1. 请遵循官方环境设置说明 [^8]。

    ¥Follow the official Environment Setup instructions[^8].

上次测试演示时,Android API 的最新版本是 34。NativeScript 不支持该 API 级别。npx -p nativescript ns doctor ios 中的确切错误消息明确说明了支持的版本:

¥When the demo was last tested, the latest version of the Android API was 34. NativeScript did not support that API level. The exact error message from npx -p nativescript ns doctor ios 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'.

SDK 平台 Android 13.0 ("Tiramisu") 与 NativeScript 兼容。在 NativeScript 正确支持 API 级别 34 之前,必须使用 "Tiramisu"。这需要从 Android Studio 安装以下软件包:

¥The SDK Platform Android 13.0 ("Tiramisu") was compatible with NativeScript. Until NativeScript properly supports API level 34, "Tiramisu" must be used. This requires installing the following packages from Android Studio:

  • Android 13.0 ("Tiramisu") API 级别 33

    ¥Android 13.0 ("Tiramisu") API Level 33

  • Android SDK Build-Tools 版本 33.0.2

    ¥Android SDK Build-Tools Version 33.0.2

  1. 测试 Android 开发的本地系统配置:

    ¥Test the local system configuration for Android development:

npx -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.7.2 version and is up to date.

  1. 测试 iOS 开发的本地系统配置(仅限 macOS):

    ¥Test the local system configuration for iOS development (macOS only):

npx -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 15.4.0 satisfies minimum required version 10. Getting NativeScript components versions information... Component nativescript has 8.7.2 version and is up to date.

基础项目

¥Base Project

  1. 创建一个 NativeScript + Angular 应用框架:

    ¥Create a skeleton NativeScript + Angular app:

npx -p nativescript ns create SheetJSNS --ng
  1. 在 Android 模拟器中启动应用以验证应用:

    ¥Launch the app in the android simulator to verify the app:

cd SheetJSNS
npx -p nativescript ns run android

(可能还要等一下)

¥(this may take a while)

模拟器启动并显示测试应用后,选择终端并按 CTRL+C 结束脚本。在 Windows 上,如果提示输入 Terminate batch job,请键入 y 并按 Enter。

¥Once the simulator launches and the test app is displayed, end the script by selecting the terminal and pressing CTRL+C. On Windows, if prompted to Terminate batch job, type y and press Enter.

如果模拟器未运行,nativescript 可能会失败并显示以下消息:

¥If the emulator is not running, nativescript may fail with the message:

Emulator start failed with: No emulator image available for device identifier 'undefined'.

添加 SheetJS

¥Add SheetJS

本节的目标是显示 SheetJS 库版本号。

¥The goal of this section is to display the SheetJS library version number.

  1. 从项目文件夹中,安装 SheetJS NodeJS 模块:

    ¥From the project folder, install the SheetJS NodeJS module:

npm i --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
  1. 编辑 src/app/item/items.component.ts,以便组件导入 SheetJS 版本字符串并将其添加到组件中的 version 变量中:

    ¥Edit src/app/item/items.component.ts so that the component imports the SheetJS version string and adds it to a version variable in the component:

src/app/item/items.component.ts (add highlighted lines)
import { version } from 'xlsx';
import { Component, OnInit } from '@angular/core'

// ...

export class ItemsComponent implements OnInit {
items: Array<Item>
version = `SheetJS - ${version}`;

constructor(private itemService: ItemService) {}
// ...
  1. 编辑模板 src/app/item/items.component.html 以在操作栏标题中引用 version

    ¥Edit the template src/app/item/items.component.html to reference version in the title of the action bar:

src/app/item/items.component.html (edit highlighted line)
<ActionBar [title]="version"></ActionBar>

<GridLayout>
<!-- ... -->
  1. 结束脚本并在 Android 模拟器中重新启动应用:

    ¥End the script and relaunch the app in the Android simulator:

npx -p nativescript ns run android

标题栏应显示版本。

¥The title bar should show the version.

NativeScript Step 4

本地文件

¥Local Files

  1. 将导入和导出按钮添加到模板中:

    ¥Add the Import and Export buttons to the template:

src/app/item/items.component.html (add highlighted lines)
<ActionBar [title]="version"></ActionBar>

<StackLayout>
<StackLayout orientation="horizontal">
<Button text="Import File" (tap)="import()" style="padding: 10px"></Button>
<Button text="Export File" (tap)="export()" style="padding: 10px"></Button>
</StackLayout>
<ListView [items]="items">
<!-- ... -->
</ListView>
</StackLayout>
  1. 在组件脚本中添加 importexport 方法:

    ¥Add the import and export methods in the component script:

src/app/item/items.component.ts
import { version, utils, read, write } from 'xlsx';
import { Dialogs, getFileAccess } from '@nativescript/core';
import { Folder, knownFolders, path } from '@nativescript/core/file-system';
import { Component, OnInit } from '@angular/core'

import { Item } from './item'
import { ItemService } from './item.service'

function get_url_for_filename(filename: string): string {
const target: Folder = knownFolders.documents() || knownFolders.ios.sharedPublic();
return path.normalize(target.path + "///" + filename);
}

@Component({
selector: 'ns-items',
templateUrl: './items.component.html',
})
export class ItemsComponent implements OnInit {
items: Array<Item>
version: string = `SheetJS - ${version}`;

constructor(private itemService: ItemService) {}

ngOnInit(): void {
this.items = this.itemService.getItems()
}

/* Import button */
async import() {
}

/* Export button */
async export() {
}
}
  1. 结束脚本并在 Android 模拟器中重新启动应用:

    ¥End the script and relaunch the app in the Android simulator:

npx -p nativescript ns run android

标题下方应出现两个按钮:

¥Two buttons should appear just below the header:

NativeScript Step 5

  1. 通过添加高亮的行来实现导入和导出:

    ¥Implement import and export by adding the highlighted lines:

src/app/item/items.component.ts (add highlighted lines)
  /* Import button */
async import() {
/* find appropriate path */
const url = get_url_for_filename("SheetJSNS.xls");

try {
await Dialogs.alert(`Attempting to read from SheetJSNS.xls at ${url}`);
/* get data */
const ab: ArrayBuffer = await getFileAccess().readBufferAsync(url);

/* read workbook */
const wb = read(ab);

/* grab first sheet */
const wsname: string = wb.SheetNames[0];
const ws = wb.Sheets[wsname];

/* update table */
this.items = utils.sheet_to_json<Item>(ws);
} catch(e) { await Dialogs.alert(e.message); }
}

/* Export button */
async export() {
/* find appropriate path */
const url = get_url_for_filename("SheetJSNS.xls");

try {
/* create worksheet from data */
const ws = utils.json_to_sheet(this.items);

/* create workbook from worksheet */
const wb = utils.book_new();
utils.book_append_sheet(wb, ws, "Sheet1");

/* generate Uint8Array */
const u8: Uint8Array = write(wb, { bookType: 'xls', type: 'buffer' });

/* attempt to save Uint8Array to file */
await getFileAccess().writeBufferAsync(url, global.isAndroid ? (Array.from(u8) as any) : u8);
await Dialogs.alert(`Wrote to SheetJSNS.xls at ${url}`);
} catch(e) { await Dialogs.alert(e.message); }
}

安卓

¥Android

  1. 在 Android 模拟器中启动应用:

    ¥Launch the app in the Android Simulator:

npx -p nativescript ns run android

如果应用没有自动启动,请手动打开 SheetJSNS 应用。

¥If the app does not automatically launch, manually open the SheetJSNS app.

  1. 点击 "导出文件"。将出现一个对话框,打印文件的写入位置。通常 URL 是 /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls

    ¥Tap "Export File". A dialog will print where the file was written. Typically the URL is /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls

  2. 从模拟器中提取文件。应在新终端或 PowerShell 窗口中运行以下命令:

    ¥Pull the file from the simulator. The following commands should be run in a new terminal or PowerShell window:

adb root
adb pull /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls SheetJSNS.xls

如果模拟器无法获得 root 权限,则以下命令在 macOS 中有效:

¥If the emulator cannot be rooted, the following command works in macOS:

adb shell "run-as org.nativescript.SheetJSNS cat /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls" > SheetJSNS.xls
  1. 使用电子表格编辑器打开 SheetJSNS.xls

    ¥Open SheetJSNS.xls with a spreadsheet editor.

在标题行之后,插入一行,其中单元格 A2 = 0、B2 = SheetJS、C2 = Library:

¥After the header row, insert a row with cell A2 = 0, B2 = SheetJS, C2 = Library:

id | name       | role
0 | SheetJS | Library
1 | Ter Stegen | Goalkeeper
3 | Piqué | Defender
...
  1. 将文件推回模拟器:

    ¥Push the file back to the simulator:

adb push SheetJSNS.xls /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls

如果模拟器无法获得 root 权限,则以下命令在 macOS 中有效:

¥If the emulator cannot be rooted, the following command works in macOS:

dd if=SheetJSNS.xls | adb shell "run-as org.nativescript.SheetJSNS dd of=/data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls"
  1. 点击 "导入文件"。一个对话框将打印所读取文件的路径。列表中的第一项将会更改。

    ¥Tap "Import File". A dialog will print the path of the file that was read. The first item in the list will change.

NativeScript Step 6

iOS

iOS 测试只能在运行 macOS 的 Apple 硬件上执行!

¥iOS testing can only be performed on Apple hardware running macOS!

Xcode 和 iOS 模拟器在 Windows 或 Linux 上不可用。

¥Xcode and iOS simulators are not available on Windows or Linux.

向下滚动到 "获取文件" 以进行 Android 设备测试。

¥Scroll down to "Fetching Files" for Android device testing.

  1. 在 iOS 模拟器中启动应用:

    ¥Launch the app in the iOS Simulator:

npx -p nativescript ns run ios
  1. 点击 "导出文件"。将出现一个对话框,打印文件的写入位置。

    ¥Tap "Export File". A dialog will print where the file was written.

  2. 使用电子表格编辑器打开该文件。

    ¥Open the file with a spreadsheet editor.

在标题行之后,插入一行,其中单元格 A2 = 0、B2 = SheetJS、C2 = Library:

¥After the header row, insert a row with cell A2 = 0, B2 = SheetJS, C2 = Library:

id | name       | role
0 | SheetJS | Library
1 | Ter Stegen | Goalkeeper
3 | Piqué | Defender
...
  1. 保存文件后重新启动应用。

    ¥Restart the app after saving the file.

  2. 点击 "导入文件"。一个对话框将打印所读取文件的路径。列表中的第一项将更改:

    ¥Tap "Import File". A dialog will print the path of the file that was read. The first item in the list will change:

NativeScript Step 7

获取文件

¥Fetching Files

  1. src/app/item/items.component.ts 中,使 ngOnInit 异步:

    ¥In src/app/item/items.component.ts, make ngOnInit asynchronous:

src/app/item/items.component.ts (replace existing function)
  async ngOnInit(): Promise<void> {
this.items = await this.itemService.getItems()
}
  1. item.service.ts 替换为以下内容:

    ¥Replace item.service.ts with the following:

src/app/item/item.service.ts
import { Injectable } from '@angular/core'

import { knownFolders, path, getFileAccess } from '@nativescript/core'
import { getFile } from '@nativescript/core/http';
import { read, utils } from 'xlsx';

import { Item } from './item'
interface IPresident { Name: string; Index: number };

@Injectable({ providedIn: 'root' })
export class ItemService {
private items: Array<Item>;

async getItems(): Promise<Array<Item>> {
/* fetch https://xlsx.nodejs.cn/pres.xlsx */
const temp: string = path.join(knownFolders.temp().path, "pres.xlsx");
const ab = await getFile("https://xlsx.nodejs.cn/pres.xlsx", temp)
/* read the temporary file */
const wb = read(await getFileAccess().readBufferAsync(ab.path));
/* translate the first worksheet to the required Item type */
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
return this.items = data.map((pres, id) => ({id, name: pres.Name, role: ""+pres.Index} as Item));
}

getItem(id: number): Item {
return this.items.filter((item) => item.id === id)[0]
}
}
  1. 结束脚本并在 Android 模拟器中重新启动应用:

    ¥End the script and relaunch the app in the Android simulator:

npx -p nativescript ns run android

该应用应显示总统数据。

¥The app should show Presidential data.

安卓设备

¥Android Device

  1. 使用 USB 电缆连接 Android 设备。

    ¥Connect an Android device using a USB cable.

如果设备要求允许 USB 调试,请点击 "允许"。

¥If the device asks to allow USB debugging, tap "Allow".

  1. 关闭所有 Android/iOS 模拟器。

    ¥Close any Android / iOS emulators.

  2. 在 Android 应用中启用 "传统外部存储"。清单存储在 App_Resources/Android/src/main/AndroidManifest.xml

    ¥Enable "Legacy External Storage" in the Android app. The manifest is stored at App_Resources/Android/src/main/AndroidManifest.xml:

App_Resources/Android/src/main/AndroidManifest.xml (add highlighted line)
  <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">
  1. 安装 @nativescript-community/perms 依赖:

    ¥Install the @nativescript-community/perms dependency:

npm i --save @nativescript-community/perms
  1. 将高亮的行添加到 items.component.ts

    ¥Add the highlighted lines to items.component.ts:

  • 从 NativeScript 核心导入 File,从新依赖导入 request

    ¥Import File from NativeScript core and request from the new dependency:

items.component.ts (add highlighted lines)
import { Dialogs, getFileAccess, Utils } from '@nativescript/core';
import { request } from '@nativescript-community/perms';
import { Folder, knownFolders, path, File } from '@nativescript/core/file-system';
import { Component, OnInit } from '@angular/core'
// ...
  • export 方法中添加一个新的写操作:

    ¥Add a new write operation to the export method:

items.component.ts (add highlighted lines)
      /* attempt to save Uint8Array to file */
await getFileAccess().writeBufferAsync(url, global.isAndroid ? (Array.from(u8) as any) : u8);
await Dialogs.alert(`Wrote to SheetJSNS.xls at ${url}`);

if(global.isAndroid) {
/* request permissions */
const res = await request('storage');
/* write to Downloads folder */
const dl = android.os.Environment.getExternalStoragePublicDirectory(android.os.Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
File.fromPath(dl + "/SheetJSNS.xls").writeSync(Array.from(u8));
}
} catch(e) { await Dialogs.alert(e.message); }
  1. 构建 APK 并在设备上运行:

    ¥Build APK and run on device:

npx -p nativescript ns run android

如果 Android 模拟器已关闭并且 Android 设备已连接,则最后一个命令将构建 APK 并安装在设备上。

¥If the Android emulators are closed and an Android device is connected, the last command will build an APK and install on the device.

Android Device Testing (click to hide)

当应用启动时,如果加载了 SheetJS 库并且设备已连接到互联网,则应显示总统列表。

¥When the app launches, if the SheetJS library is loaded and if the device is connected to the Internet, a list of Presidents should be displayed.

点击 "导出文件"。该应用将显示警报。点击 "OK"。

¥Tap "Export File". The app will show an alert. Tap "OK".

切换到 "文件" 应用并打开 "下载" 文件夹。应该有一个名为 SheetJSNS.xls.txt 的新文件。

¥Switch to the "Files" app and open the "Downloads" folder. There should be a new file named SheetJSNS.xls.

iOS 设备

¥iOS Device

  1. 使用 USB 线连接 iOS 设备

    ¥Connect an iOS device using a USB cable

  2. 关闭所有 Android/iOS 模拟器。

    ¥Close any Android / iOS emulators.

  3. 启用开发者代码签名证书:

    ¥Enable developer code signing certificates:

在 Xcode 中打开 platforms/ios/SheetJSNS.xcodeproj/project.xcworkspace。选择 "项目导航器",然后选择 "应用" 项目。在主视图中,选择 "签名和能力"。在 "签名" 下,在下拉菜单中选择一个团队。

¥Open platforms/ios/SheetJSNS.xcodeproj/project.xcworkspace in Xcode. Select the "Project Navigator" and select the "App" project. In the main view, select "Signing & Capabilities". Under "Signing", select a team in the dropdown menu.

  1. 在设备上运行:

    ¥Run on device:

npx -p nativescript ns run ios
iOS Device Testing (click to hide)

当应用启动时,如果加载了 SheetJS 库并且设备已连接到互联网,则应显示总统列表。

¥When the app launches, if the SheetJS library is loaded and if the device is connected to the Internet, a list of Presidents should be displayed.

点击 "导出文件"。该应用将显示警报。点击 "OK"。

¥Tap "Export File". The app will show an alert. Tap "OK".

切换到 "文件" 应用并打开 "下载" 文件夹。应该有一个名为 SheetJSNS.xls.txt 的新文件。

¥Switch to the "Files" app and open the "Downloads" folder. There should be a new file named SheetJSNS.xls.

[^1]: 见 read 于 "读取文件"

¥See read in "Reading Files"

[^2]: 见 "工作簿对象"

¥See "Workbook Object"

[^3]: 见 sheet_to_json 于 "实用工具"

¥See sheet_to_json in "Utilities"

[^4]: 见 write 于 "写入文件"

¥See write in "Writing Files"

[^5]: 见 json_to_sheet 于 "实用工具"

¥See json_to_sheet in "Utilities"

[^6]: 有关 book_newbook_append_sheet 的详细信息,请参阅 "工作簿助手" 于 "实用工具"

¥See "Workbook Helpers" in "Utilities" for details on book_new and book_append_sheet.

[^7]: 见 read 于 "读取文件"

¥See read in "Reading Files"

[^8]: 请参阅 NativeScript 文档中的 "本地设置"。对于 Windows 和 Linux,请遵循 "安卓" 说明。对于 macOS,请遵循 iOS 和 Android 说明。

¥See "Local setup" in the NativeScript documentation. For Windows and Linux, follow the "Android" instructions. For macOS, follow both the iOS and Android instructions.