forked from sheetjs/docs.sheetjs.com
		
	rn
This commit is contained in:
		
							parent
							
								
									5f52a9f6b6
								
							
						
					
					
						commit
						74ac713193
					
				@ -1,5 +1,7 @@
 | 
			
		||||
---
 | 
			
		||||
title: React Native
 | 
			
		||||
sidebar_label: React Native
 | 
			
		||||
description: Build data-intensive mobile apps with React Native. Seamlessly integrate spreadsheets into your app using SheetJS. Securely process and generate Excel files in the field.
 | 
			
		||||
pagination_prev: demos/static/index
 | 
			
		||||
pagination_next: demos/desktop/index
 | 
			
		||||
sidebar_position: 1
 | 
			
		||||
@ -7,13 +9,26 @@ sidebar_custom_props:
 | 
			
		||||
  summary: React + Native Rendering
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Sheets on the Go with React Native
 | 
			
		||||
 | 
			
		||||
import current from '/version.js';
 | 
			
		||||
import Tabs from '@theme/Tabs';
 | 
			
		||||
import TabItem from '@theme/TabItem';
 | 
			
		||||
import CodeBlock from '@theme/CodeBlock';
 | 
			
		||||
 | 
			
		||||
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
 | 
			
		||||
from the main `App.js` entrypoint or any script in the project.
 | 
			
		||||
[React Native](https://reactnative.dev/) is a mobile app framework. It builds
 | 
			
		||||
iOS and Android apps that use JavaScript for describing layouts and events.
 | 
			
		||||
 | 
			
		||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
 | 
			
		||||
data from spreadsheets.
 | 
			
		||||
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
- ["Fetching Remote Data"](#fetching-remote-data) uses the built-in `fetch` to
 | 
			
		||||
download and parse remote workbook files.
 | 
			
		||||
- ["Local Files"](#local-files) uses native libraries to read and write files on
 | 
			
		||||
the device.
 | 
			
		||||
 | 
			
		||||
The "Complete Example" creates an app that looks like the screenshots below:
 | 
			
		||||
 | 
			
		||||
@ -30,17 +45,9 @@ The "Complete Example" creates an app that looks like the screenshots below:
 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
["Fetching Remote Data"](#fetching-remote-data) uses the built-in `fetch` to
 | 
			
		||||
download and parse remote workbook files.
 | 
			
		||||
:::caution pass
 | 
			
		||||
 | 
			
		||||
["Native Libraries"](#native-libraries) uses native libraries to read and write
 | 
			
		||||
files in the local device.
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
**Before reading this demo, follow the official React Native CLI Guide!**
 | 
			
		||||
 | 
			
		||||
Development Environment Guide: <https://reactnative.dev/docs/environment-setup>
 | 
			
		||||
**Before testing this demo, follow the official React Native CLI Guide!**[^1]
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
@ -48,42 +55,178 @@ a sample app in the Android and the iOS (if applicable) simulators.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## Integration Details
 | 
			
		||||
 | 
			
		||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
 | 
			
		||||
imported from the main `App.js` entrypoint or any script in the project.
 | 
			
		||||
 | 
			
		||||
### Internal State
 | 
			
		||||
 | 
			
		||||
For simplicity, this demo uses an "Array of Arrays"[^2] as the internal state.
 | 
			
		||||
 | 
			
		||||
<table><thead><tr><th>Spreadsheet</th><th>Array of Arrays</th></tr></thead><tbody><tr><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
[
 | 
			
		||||
  ["Name", "Index"],
 | 
			
		||||
  ["Bill Clinton", 42],
 | 
			
		||||
  ["GeorgeW Bush", 43],
 | 
			
		||||
  ["Barack Obama", 44],
 | 
			
		||||
  ["Donald Trump", 45],
 | 
			
		||||
  ["Joseph Biden", 46]
 | 
			
		||||
]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
Starting from a SheetJS worksheet object, `sheet_to_json`[^3] with the `header`
 | 
			
		||||
option can generate an array of arrays:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* 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:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* 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] builds a SheetJS worksheet object from the array of arrays:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* 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;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Displaying Data
 | 
			
		||||
 | 
			
		||||
The demos uses `react-native-table-component` to display the first worksheet.
 | 
			
		||||
 | 
			
		||||
The demos use components similar to the example below:
 | 
			
		||||
 | 
			
		||||
```jsx
 | 
			
		||||
import { ScrollView } from 'react-native';
 | 
			
		||||
import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
 | 
			
		||||
 | 
			
		||||
(
 | 
			
		||||
  {/* Horizontal scroll */}
 | 
			
		||||
  <ScrollView horizontal={true} >
 | 
			
		||||
    {/* Table container */}
 | 
			
		||||
    <Table>
 | 
			
		||||
      {/* Frozen Header Row */}
 | 
			
		||||
      <TableWrapper>
 | 
			
		||||
        {/* First row */}
 | 
			
		||||
        <Row data={data[0]} widthArr={widths}/>
 | 
			
		||||
      </TableWrapper>
 | 
			
		||||
      {/* Scrollable Data Rows */}
 | 
			
		||||
      <ScrollView>
 | 
			
		||||
        <TableWrapper>
 | 
			
		||||
          {/* Remaining Rows */}
 | 
			
		||||
          <Rows data={data.slice(1)} widthArr={widths}/>
 | 
			
		||||
        </TableWrapper>
 | 
			
		||||
      </ScrollView>
 | 
			
		||||
    </Table>
 | 
			
		||||
  </ScrollView>
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`data.slice(1)` in the `Rows` component returns data starting from the second
 | 
			
		||||
row. This neatly skips the first header row.
 | 
			
		||||
 | 
			
		||||
## Fetching Remote Data
 | 
			
		||||
 | 
			
		||||
:::info
 | 
			
		||||
React Native versions starting from `0.72.0`[^5] support binary data with `fetch`.
 | 
			
		||||
 | 
			
		||||
React Native `0.72.0` will support binary data with `fetch`. For older versions,
 | 
			
		||||
[a native library](#native-libraries) can provide support.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
React Native 0.72.0 will support binary data with `fetch`:
 | 
			
		||||
This snippet downloads and parses <https://sheetjs.com/pres.xlsx>:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* fetch data into an ArrayBuffer */
 | 
			
		||||
const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer();
 | 
			
		||||
const ab = await (await fetch("https://sheetjs.com/pres.xlsx")).arrayBuffer();
 | 
			
		||||
/* parse data */
 | 
			
		||||
const wb = XLSX.read(ab);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Fetch Demo
 | 
			
		||||
 | 
			
		||||
The following demo uses `react-native-table-component` to display the first
 | 
			
		||||
worksheet in a simple table.
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was tested on an Intel Mac on 2023 April 24 with RN `0.72.0-rc.1`.
 | 
			
		||||
This demo was tested on an Intel Mac on 2023 July 02 with RN `0.72.1`.
 | 
			
		||||
 | 
			
		||||
The iOS simulator runs iOS 16.2 on an iPhone SE (3rd generation).
 | 
			
		||||
 | 
			
		||||
The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
1) Create project:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx react-native init SheetJSRNFetch --version="0.72.0-rc.1"
 | 
			
		||||
npx -y react-native@0.72.1 init SheetJSRNFetch --version="0.72.1"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install shared dependencies:
 | 
			
		||||
@ -95,69 +238,46 @@ npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
 | 
			
		||||
npm i -S react-native-table-component@1.2.0 @types/react-native-table-component`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
Refresh iOS project by running `pod install` from the `ios` subfolder:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cd ios; pod install; cd ..
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Download [`App.tsx`](pathname:///reactnative/App.tsx) and replace:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -LO https://docs.sheetjs.com/reactnative/App.tsx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**iOS Testing**
 | 
			
		||||
 | 
			
		||||
Start the iOS emulator:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx react-native run-ios
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
When opened, the app should look like the "Before" screenshot below.  After
 | 
			
		||||
tapping "Import data from a spreadsheet", the app should show new data:
 | 
			
		||||
 | 
			
		||||
<table><thead><tr>
 | 
			
		||||
  <th>Before</th>
 | 
			
		||||
  <th>After</th>
 | 
			
		||||
</tr></thead><tbody><tr><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
**Android Testing**
 | 
			
		||||
 | 
			
		||||
Start the Android emulator:
 | 
			
		||||
4) Install or switch to Java 11[^6]
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
When the demo was last tested on macOS, `java -version` displayed the following:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
openjdk version "11.0.19" 2023-04-18 LTS
 | 
			
		||||
OpenJDK Runtime Environment Zulu11.64+19-CA (build 11.0.19+7-LTS)
 | 
			
		||||
OpenJDK 64-Bit Server VM Zulu11.64+19-CA (build 11.0.19+7-LTS, mixed mode)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
5) Start the Android emulator:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx react-native run-android
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
:::caution pass
 | 
			
		||||
 | 
			
		||||
When this demo was last tested, the simulator failed with the message
 | 
			
		||||
If the initial launch fails with an error referencing the emulator, manually
 | 
			
		||||
start the emulator and try again.
 | 
			
		||||
 | 
			
		||||
> Unable to load script.  Make sure you're either Running Metro ...
 | 
			
		||||
 | 
			
		||||
The workaround is to launch Metro directly:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx react-native start
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Press `a` in the terminal window and Metro will try to reload the app.
 | 
			
		||||
Gradle errors typically stem from a Java version mismatch. Run `java -version`
 | 
			
		||||
and verify that the Java major version is 11.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
When opened, the app should look like the "Before" screenshot below.  After
 | 
			
		||||
tapping "Import data from a spreadsheet", the app should show new data:
 | 
			
		||||
6) When opened, the app should look like the "Before" screenshot below. After
 | 
			
		||||
tapping "Import data from a spreadsheet", verify that the app shows new data:
 | 
			
		||||
 | 
			
		||||
<table><thead><tr>
 | 
			
		||||
  <th>Before</th>
 | 
			
		||||
@ -172,10 +292,45 @@ tapping "Import data from a spreadsheet", the app should show new data:
 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
**iOS Testing**
 | 
			
		||||
 | 
			
		||||
## Native Libraries
 | 
			
		||||
:::warning pass
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
iOS testing requires macOS. It does not work on Windows.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
7) Refresh iOS project by running `pod install` from the `ios` subfolder:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cd ios; pod install; cd ..
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
8) Start the iOS emulator:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx react-native run-ios
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
9) When opened, the app should look like the "Before" screenshot below.  After
 | 
			
		||||
tapping "Import data from a spreadsheet", verify that the app shows new data:
 | 
			
		||||
 | 
			
		||||
<table><thead><tr>
 | 
			
		||||
  <th>Before</th>
 | 
			
		||||
  <th>After</th>
 | 
			
		||||
</tr></thead><tbody><tr><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td><td>
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
## Local Files
 | 
			
		||||
 | 
			
		||||
:::warning pass
 | 
			
		||||
 | 
			
		||||
React Native does not provide a native file picker or a method for reading and
 | 
			
		||||
writing data from documents on the devices. A third-party library must be used.
 | 
			
		||||
@ -187,40 +342,41 @@ consulted before picking a library.
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
The following table lists tested file plugins.  "OS" lists tested platforms
 | 
			
		||||
("A" for Android and "I" for iOS).  "Copy" indicates whether an explicit copy
 | 
			
		||||
is needed (file picker copies to cache directory and file plugin reads cache).
 | 
			
		||||
("A" for Android and "I" for iOS).
 | 
			
		||||
 | 
			
		||||
| File system Plugin         | File Picker Plugin             |  OS  | Copy |
 | 
			
		||||
|:---------------------------|:-------------------------------|:----:|:-----|
 | 
			
		||||
| `react-native-file-access` | `react-native-document-picker` | `AI` |      |
 | 
			
		||||
| `react-native-blob-util`   | `react-native-document-picker` | `AI` | YES  |
 | 
			
		||||
| `rn-fetch-blob`            | `react-native-document-picker` | `AI` | YES  |
 | 
			
		||||
| `react-native-fs`          | `react-native-document-picker` | `AI` | YES  |
 | 
			
		||||
| `expo-file-system`         | `expo-document-picker`         | ` I` | YES  |
 | 
			
		||||
| File system Plugin         | File Picker Plugin             |  OS  |
 | 
			
		||||
|:---------------------------|:-------------------------------|:----:|
 | 
			
		||||
| `react-native-file-access` | `react-native-document-picker` | `AI` |
 | 
			
		||||
| `react-native-blob-util`   | `react-native-document-picker` | `AI` |
 | 
			
		||||
| `rn-fetch-blob`            | `react-native-document-picker` | `AI` |
 | 
			
		||||
| `react-native-fs`          | `react-native-document-picker` | `AI` |
 | 
			
		||||
| `expo-file-system`         | `expo-document-picker`         | ` I` |
 | 
			
		||||
 | 
			
		||||
### RN File Picker
 | 
			
		||||
 | 
			
		||||
The "File Picker" library handles two platform-specific steps:
 | 
			
		||||
 | 
			
		||||
1) Show a view that allows users to select a file from their device
 | 
			
		||||
 | 
			
		||||
2) Copy the selected file to a location that can be read by the application
 | 
			
		||||
 | 
			
		||||
The following libraries have been tested:
 | 
			
		||||
 | 
			
		||||
#### `react-native-document-picker`
 | 
			
		||||
 | 
			
		||||
<details open><summary><b>Selecting a file</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
When a copy is not needed:
 | 
			
		||||
The setting `copyTo: "cachesDirectory"` must be set:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { pickSingle } from 'react-native-document-picker';
 | 
			
		||||
 | 
			
		||||
const f = await pickSingle({allowMultiSelection: false, mode: "open" });
 | 
			
		||||
const path = f.uri; // this path can be read by RN file plugins
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
When a copy is needed:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { pickSingle } from 'react-native-document-picker';
 | 
			
		||||
 | 
			
		||||
const f = await pickSingle({allowMultiSelection: false, copyTo: "cachesDirectory", mode: "open" });
 | 
			
		||||
const f = await pickSingle({
 | 
			
		||||
  allowMultiSelection: false,
 | 
			
		||||
  // highlight-next-line
 | 
			
		||||
  copyTo: "cachesDirectory",
 | 
			
		||||
  mode: "open"
 | 
			
		||||
});
 | 
			
		||||
const path = f.fileCopyUri; // this path can be read by RN file plugins
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -240,7 +396,7 @@ const result = await DocumentPicker.getDocumentAsync({
 | 
			
		||||
  copyToCacheDirectory: true,
 | 
			
		||||
  type: ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
 | 
			
		||||
});
 | 
			
		||||
const path = result.uri;
 | 
			
		||||
const path = result.uri; // this path can be read by RN file plugins
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
@ -433,11 +589,11 @@ await FileSystem.writeAsStringAsync(FileSystem.documentDirectory + "sheetjs.xlsx
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
## Demo
 | 
			
		||||
### Demo
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was tested on an Intel Mac on 2023 April 30 with RN `0.72.0-rc.1`.
 | 
			
		||||
This demo was tested on an Intel Mac on 2023 July 02 with RN `0.72.1`.
 | 
			
		||||
 | 
			
		||||
The iOS simulator runs iOS 16.2 on an iPhone 14.
 | 
			
		||||
 | 
			
		||||
@ -449,8 +605,8 @@ The Android simulator runs Android 12 (S) Platform 31 on a Pixel 5.
 | 
			
		||||
 | 
			
		||||
There are many moving parts and pitfalls with React Native apps. It is strongly
 | 
			
		||||
recommended to follow the official React Native tutorials for iOS and Android
 | 
			
		||||
before approaching this demo.  Details like creating an Android Virtual Device
 | 
			
		||||
are not covered here.
 | 
			
		||||
before approaching this demo.[^7] Details including Android Virtual Device
 | 
			
		||||
configuration are not covered here.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -459,7 +615,7 @@ This example tries to separate the library-specific functions.
 | 
			
		||||
1) Create project:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx react-native init SheetJSRN --version="0.72.0-rc.1"
 | 
			
		||||
npx react-native init SheetJSRN --version="0.72.1"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install shared dependencies:
 | 
			
		||||
@ -519,7 +675,6 @@ import { Platform } from 'react-native';
 | 
			
		||||
import RNFetchBlob from 'react-native-blob-util';
 | 
			
		||||
 | 
			
		||||
async function pickAndParse() {
 | 
			
		||||
  /* rn-fetch-blob / react-native-blob-util need a copy */
 | 
			
		||||
  const f = await pickSingle({allowMultiSelection: false, copyTo: "documentDirectory", mode: "open" });
 | 
			
		||||
  let path = f.fileCopyUri;
 | 
			
		||||
  if (Platform.OS === 'ios') path = path.replace(/^.*\/Documents\//, RNFetchBlob.fs.dirs.DocumentDir + "/");
 | 
			
		||||
@ -560,11 +715,6 @@ import { Platform } from 'react-native';
 | 
			
		||||
import { Dirs, FileSystem } from 'react-native-file-access';
 | 
			
		||||
 | 
			
		||||
async function pickAndParse() {
 | 
			
		||||
  /* react-native-file-access in RN < 0.72 does not need a copy */
 | 
			
		||||
  //const f = await pickSingle({allowMultiSelection: false, mode: "open" });
 | 
			
		||||
  //const res = await FileSystem.readFile(f.uri, "base64");
 | 
			
		||||
  //return read(res, {type: 'base64'});
 | 
			
		||||
  /* react-native-file-access in RN >= 0.72 needs a copy */
 | 
			
		||||
  const f = await pickSingle({allowMultiSelection: false, copyTo: "documentDirectory", mode: "open" });
 | 
			
		||||
  let path = f.fileCopyUri;
 | 
			
		||||
  const res = await (await fetch(path)).arrayBuffer();
 | 
			
		||||
@ -603,7 +753,6 @@ import { Platform } from 'react-native';
 | 
			
		||||
import RNFetchBlob from 'rn-fetch-blob';
 | 
			
		||||
 | 
			
		||||
async function pickAndParse() {
 | 
			
		||||
  /* rn-fetch-blob / react-native-blob-util need a copy */
 | 
			
		||||
  const f = await pickSingle({allowMultiSelection: false, copyTo: "documentDirectory", mode: "open" });
 | 
			
		||||
  let path = f.fileCopyUri;
 | 
			
		||||
  if (Platform.OS === 'ios') path = path.replace(/^.*\/Documents\//, RNFetchBlob.fs.dirs.DocumentDir + "/");
 | 
			
		||||
@ -643,7 +792,6 @@ import { pickSingle } from 'react-native-document-picker';
 | 
			
		||||
import { writeFile, readFile, DocumentDirectoryPath } from 'react-native-fs';
 | 
			
		||||
 | 
			
		||||
async function pickAndParse() {
 | 
			
		||||
  /* react-native-fs needs a copy */
 | 
			
		||||
  const f = await pickSingle({allowMultiSelection: false, copyTo: "cachesDirectory", mode: "open" });
 | 
			
		||||
  const bstr = await readFile(f.fileCopyUri, 'ascii');
 | 
			
		||||
  return read(bstr, {type:'binary'});
 | 
			
		||||
@ -665,12 +813,7 @@ const make_width = ws => {
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
 | 
			
		||||
At the time of testing, Expo did not support RN 0.72 .  The project should be
 | 
			
		||||
created with React Native 0.67.2:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx react-native init SheetJSRN --version="0.67.2"
 | 
			
		||||
```
 | 
			
		||||
At the time of testing, Expo Modules were incompatible with Android projects.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -793,3 +936,11 @@ Once selected, the screen should refresh with new contents:
 | 
			
		||||
adb exec-out run-as com.sheetjsrn cat files/sheetjsw.xlsx > /tmp/sheetjsw.xlsx
 | 
			
		||||
npx xlsx-cli /tmp/sheetjsw.xlsx
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[^1]: Follow the ["React Native CLI Quickstart"](https://reactnative.dev/docs/environment-setup) and select the appropriate "Development OS".
 | 
			
		||||
[^2]: See ["Array of Arrays" in the API reference](/docs/api/utilities/array#array-of-arrays)
 | 
			
		||||
[^3]: See ["Array Output" in "Utility Functions"](/docs/api/utilities/array#array-output)
 | 
			
		||||
[^4]: See ["Array of Arrays Input" in "Utility Functions"](/docs/api/utilities/array#array-of-arrays-input)
 | 
			
		||||
[^5]: React-Native commit [`5b597b5`](https://github.com/facebook/react-native/commit/5b597b5ff94953accc635ed3090186baeecb3873) added the final piece required for `fetch` support. It landed in version `0.72.0-rc.1` and is available in official releases starting from `0.72.0`.
 | 
			
		||||
[^6]: When the demo was last tested, the Zulu11 distribution of Java 11 was installed through the macOS Brew package manager. [Direct downloads are available at `azul.com`](https://www.azul.com/downloads/?version=java-11-lts&package=jdk#zulu)
 | 
			
		||||
[^7]: Follow the ["React Native CLI Quickstart"](https://reactnative.dev/docs/environment-setup) for Android (and iOS, if applicable)
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user