7.3 KiB
title | sidebar_label | pagination_prev | pagination_next |
---|---|---|---|
Modern Spreadsheets in Stata | Stata | demos/cloud/index | demos/bigdata/index |
import current from '/version.js'; import CodeBlock from '@theme/CodeBlock';
export const b = {style: {color:"blue"}};
Stata is a statistical software package. It offers a robust C-based extension system.
SheetJS is a JavaScript library for reading and writing data from spreadsheets.
This demo uses SheetJS to pull data from a spreadsheet for further analysis within Stata. We'll create a Stata native extension that loads the Duktape JavaScript engine and uses the SheetJS library to read data from spreadsheets and converts to a Stata-friendly format.
flowchart LR
ofile[(workbook\nXLSB file)]
nfile[(clean file\nXLSX)]
data[[Stata\nVariables]]
ofile --> |Stata Extension\nSheetJS + Duktape| nfile
nfile --> |Stata command\nimport excel|data
The demo will read a Numbers workbook and generate variables for each column. A sample Stata session is shown below:
:::note
This demo was last tested by SheetJS users on 2023 October 09.
:::
:::info pass
Stata has limited support for processing spreadsheets through the import excel
command1. At the time of writing, it lacked support for XLSB, NUMBERS, and
other common spreadsheet formats.
SheetJS libraries help fill the gap by normalizing spreadsheets to a form that Stata can understand.
:::
Integration Details
The current recommendation involves a native plugin that reads arbitrary files and generates clean XLSX files that Stata can import.
The extension function ultimately pairs the SheetJS read
2 and write
3
methods to read data from the old file and write a new file:
var wb = XLSX.read(original_file_data, {type: "buffer"});
var new_file_data = XLSX.write(wb, {type: "array", bookType: "xlsx"});
The extension function cleanfile
will take one or two arguments:
plugin call cleanfile, "pres.numbers"
will generate sheetjs.tmp.xlsx
from
the first argument ("pres.numbers"
) and print instructions to load the file.
plugin call cleanfile, "pres.numbers" verbose
will additionally print CSV
contents of each worksheet in the workbook.
flowchart LR
ofile{{File\nName}}
subgraph JS Operations
ojbuf[(Buffer\nFile Bytes)]
wb(((SheetJS\nWorkbook)))
njbuf[(Buffer\nXLSX bytes)]
end
obuf[(File\nbytes)]
nbuf[(New file\nbytes)]
nfile[(XLSX\nFile)]
ofile --> |C\nRead File| obuf
obuf --> |Duktape\nBuffer Ops| ojbuf
ojbuf --> |SheetJS\n`read`| wb
wb --> |SheetJS\n`write`| njbuf
njbuf --> |Duktape\nBuffer Ops| nbuf
nbuf --> |C\nWrite File| nfile
C Extensions
Stata C extensions are shared libraries or DLLs that use special Stata methods for parsing arguments and returning values.
Arguments are passed to the stata_call
function in the DLL.
SF_display
and SF_error
display text and error messages respectively.
Duktape JS Engine
This demo uses the Duktape JavaScript engine. The SheetJS + Duktape demo covers engine integration details in more detail.
The SheetJS Standalone scripts can be loaded in Duktape by reading the source from the filesystem.
Complete Demo
:::info pass
This demo was tested in Windows x64. The path names and build commands will differ in other platforms and operating systems.
:::
The cleanfile.c
extension defines one plugin
function. It can be chained with import excel
:
program cleanfile, plugin
plugin call cleanfile, "pres.numbers" verbose
program drop cleanfile
import excel "sheetjs.tmp.xlsx", firstrow
Create Plugin
-
Ensure "Windows Subsystem for Linux" (WSL) and Visual Studio are installed.
-
Open a new "x64 Native Tools Command Prompt" window and create a project folder
c:\sheetjs-stata
:
cd c:\
mkdir sheetjs-stata
cd sheetjs-stata
- Enter WSL:
bash
- Download
stplugin.c
andstplugin.h
from the Stata website:
curl -LO https://www.stata.com/plugins/stplugin.c
curl -LO https://www.stata.com/plugins/stplugin.h
- Still within WSL, install Duktape:
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
mv duktape-2.7.0/src/*.{c,h} .
- Still within WSL, download the demo source
cleanfile.c
:
curl -LO https://docs.sheetjs.com/stata/cleanfile.c
- Exit WSL:
exit
The window will return to the command prompt.
- Build the DLL:
cl /LD cleanfile.c stplugin.c duktape.c
Install Plugin
- Copy the DLL to
cleanfile.plugin
in the Stata data directory. For example, with a shared data directoryc:\data
:
mkdir c:\data
copy cleanfile.dll c:\data\cleanfile.plugin
Download SheetJS Scripts
- Move to the
c:\data
directory
cd c:\data
- Enter WSL
bash
- Within WSL, download SheetJS scripts and the test file.
{\ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js curl -LO https://sheetjs.com/pres.numbers
}
- Exit WSL:
exit
The window will return to the command prompt.
Stata Test
:::note pass
The screenshot in the introduction shows the result of steps 13 - 19
:::
-
Open Stata
-
Move to the
c:\data
directory in Stata:
cd c:\data
- Load the
cleanfile
plugin:
program cleanfile, plugin
- Read the
pres.numbers
test file:
plugin call cleanfile, "pres.numbers" verbose
The result will show the data from pres.numbers
:
. plugin call cleanfile, "pres.numbers" verbose{'\n'} Worksheet 0 Name: Sheet1{'\n'} Name,Index{'\n'} Bill Clinton,42{'\n'} GeorgeW Bush,43{'\n'} Barack Obama,44{'\n'} Donald Trump,45{'\n'} Joseph Biden,46{'\n'} {'\n'} Saved to `sheetjs.tmp.xlsx`{'\n'} import excel "sheetjs.tmp.xlsx", firstrow will read the first sheet and use headers{'\n'} for more help, see import excel
- Close the plugin:
program drop cleanfile
- Clear the current session:
clear
19) In the result of Step 16, click the link on import
excel "sheetjs.tmp.xlsx", firstrow
Alternatively, manually type the command:
import excel "sheetjs.tmp.xlsx", firstrow
The output will show the import result:
. import excel "sheetjs.tmp.xlsx", firstrow{'\n'} (2 vars, 5 obs)
- Open the Data Editor (in Browse or Edit mode) and compare to the screenshot:
-
Run
help import excel
in Stata or see "import excel" in the Stata documentation. ↩︎