| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | --- | 
					
						
							| 
									
										
										
										
											2024-04-01 10:44:10 +00:00
										 |  |  | title: VBA and Macros | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | sidebar_position: 7 | 
					
						
							|  |  |  | --- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import current from '/version.js'; | 
					
						
							|  |  |  | import Tabs from '@theme/Tabs'; | 
					
						
							|  |  |  | import TabItem from '@theme/TabItem'; | 
					
						
							|  |  |  | import CodeBlock from '@theme/CodeBlock'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 04:47:04 +00:00
										 |  |  | <details> | 
					
						
							|  |  |  |   <summary><b>File Format Support</b> (click to show)</summary> | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 10:44:10 +00:00
										 |  |  | XLSX does not support macros. The XLSM file format is nearly identical to XLSX | 
					
						
							|  |  |  | and supports macros. | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | | Formats | Basic | Storage Representation             | | 
					
						
							|  |  |  | |:--------|:-----:|:-----------------------------------| | 
					
						
							|  |  |  | | XLSM    |   ✔   | `vbaProject.bin` file in container | | 
					
						
							| 
									
										
										
										
											2023-06-14 19:32:34 +00:00
										 |  |  | | XLSX    |   ✕   | Not supported in format (use XLSM) | | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | | XLSB    |   ✔   | `vbaProject.bin` file in container | | 
					
						
							|  |  |  | | XLS     |   ✔   | Intercalated in CFB container      | | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 19:32:34 +00:00
										 |  |  | X (✕) marks features that are not supported by the file formats. There is | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | no way to embed VBA in the XLSX format. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </details> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 10:44:10 +00:00
										 |  |  | Visual Basic for Applications (VBA) is a scripting platform embedded in Excel. | 
					
						
							|  |  |  | Users can include user-defined functions and macro code within spreadsheets. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `vbaraw` property of the SheetJS workbook object is an encoded data blob | 
					
						
							|  |  |  | which includes the VBA macros and other metadata. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The SheetJS `read` and `readFile` methods do not pull VBA metadata by default. | 
					
						
							|  |  |  | If the `bookVBA` option is set to true, the `vbaraw` blob is created. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | var workbook = XLSX.read(data, { bookVBA: true }); | 
					
						
							|  |  |  | var encoded_vba_blob = workbook.vbaraw; | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The SheetJS `write` and `writeFile` methods will save the `vbaraw` blob if it is | 
					
						
							|  |  |  | present in the workbook object and if the output file format supports macros. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | workbook.vbaraw = encoded_vba_blob; | 
					
						
							|  |  |  | XLSX.writeFile(workbook, "SheetJSNewMacro.xlsm"); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :::info pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Newer versions of Excel support a new JavaScript API for writing user-defined | 
					
						
							|  |  |  | functions. Those addins are not stored in the spreadsheet files. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | [The "Excel JavaScript API" demo](/docs/demos/extensions/excelapi) covers usage | 
					
						
							|  |  |  | of SheetJS libraries within the API. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-01 10:44:10 +00:00
										 |  |  | :::tip pass | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The `vbaraw` property stores raw bytes. [SheetJS Pro](https://sheetjs.com/pro) | 
					
						
							|  |  |  | offers a special component for extracting macro text from the VBA blob, editing | 
					
						
							|  |  |  | the VBA project, and exporting new VBA blobs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Demos
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The export demos focus on [an example](pathname:///vba/SheetJSVBAFormula.xlsm) | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | that includes the following macros: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _User-defined functions_ | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```vb | 
					
						
							|  |  |  | Function GetFormulaA1(Cell As Range) As String | 
					
						
							|  |  |  |   GetFormulaA1 = Cell.Formula | 
					
						
							|  |  |  | End Function | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Function GetFormulaRC(Cell As Range) As String | 
					
						
							|  |  |  |   GetFormulaRC = Cell.Formula2R1C1 | 
					
						
							|  |  |  | End Function | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | _Event Handlers_ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```vb | 
					
						
							|  |  |  | Sub Workbook_Open() | 
					
						
							|  |  |  |   MsgBox "Hello from SheetJS!", vbOKOnly | 
					
						
							|  |  |  | End Sub | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### Copying Macros
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | After downloading the sample file, the demo extracts the VBA blob and creates | 
					
						
							|  |  |  | a new workbook including the VBA blob. Click the button to create the file and | 
					
						
							|  |  |  | open in a spreadsheet editor that supports VBA: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <Tabs groupId="platform"> | 
					
						
							|  |  |  |   <TabItem value="browser" label="Web Browser"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSVBAFormula() { return ( <button onClick={async () => { | 
					
						
							|  |  |  |   /* Extract VBA Blob from test file */ | 
					
						
							|  |  |  |   const url = "/vba/SheetJSVBAFormula.xlsm"; | 
					
						
							|  |  |  |   const raw_data = await (await fetch(url)).arrayBuffer(); | 
					
						
							|  |  |  |   const blob = XLSX.read(raw_data, {bookVBA: true}).vbaraw; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* generate worksheet and workbook */ | 
					
						
							|  |  |  |   const worksheet = XLSX.utils.aoa_to_sheet([ | 
					
						
							|  |  |  |     ["Cell", "A1", "RC"], | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |       {t:"n", f:"LEN(A1)"},      // A2 | 
					
						
							|  |  |  |       {t:"s", f:"GetFormulaA1(A2)"},  // B2 | 
					
						
							|  |  |  |       {t:"s", f:"GetFormulaRC(A2)"}   // C2 | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  |   const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  |   XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* add VBA blob to new workbook */ | 
					
						
							|  |  |  |   workbook.vbaraw = blob; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* create an XLSM file and try to save to SheetJSVBANeu.xlsm */ | 
					
						
							| 
									
										
										
										
											2024-04-01 10:44:10 +00:00
										 |  |  |   XLSX.writeFile(workbook, "SheetJSVBANeu.xlsm"); | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | }}><b>Click to Generate file!</b></button> ); } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="nodejs" label="NodeJS"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 0) Install the dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <CodeBlock language="bash">{`\ | 
					
						
							|  |  |  | npm init -y | 
					
						
							|  |  |  | npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | 
					
						
							|  |  |  | </CodeBlock> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Save the following script to `generate_file.js`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js title="generate_file.js" | 
					
						
							|  |  |  | const XLSX = require("xlsx"); | 
					
						
							|  |  |  | (async() => { | 
					
						
							|  |  |  | /* Extract VBA Blob from test file */ | 
					
						
							|  |  |  | const url = "https://docs.sheetjs.com/vba/SheetJSVBAFormula.xlsm"; | 
					
						
							|  |  |  | const raw_data = await (await fetch(url)).arrayBuffer(); | 
					
						
							|  |  |  | const blob = XLSX.read(raw_data, {bookVBA: true}).vbaraw; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* generate worksheet and workbook */ | 
					
						
							|  |  |  | const worksheet = XLSX.utils.aoa_to_sheet([ | 
					
						
							|  |  |  |   ["Cell", "A1", "RC"], | 
					
						
							|  |  |  |   [ | 
					
						
							|  |  |  |     {t:"n", f:"LEN(A1)"},      // A2 | 
					
						
							|  |  |  |     {t:"s", f:"GetFormulaA1(A2)"},  // B2 | 
					
						
							|  |  |  |     {t:"s", f:"GetFormulaRC(A2)"}   // C2 | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  | ]); | 
					
						
							|  |  |  | const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  | XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* add VBA blob to new workbook */ | 
					
						
							|  |  |  | workbook.vbaraw = blob; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* create an XLSM file and try to save to SheetJSVBANeu.xlsm */ | 
					
						
							| 
									
										
										
										
											2024-04-01 10:44:10 +00:00
										 |  |  | XLSX.writeFile(workbook, "SheetJSVBANeu.xlsm"); | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | })(); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2) Run the script: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | node generate_file.js | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This script will generate `SheetJSVBANeu.xlsm`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Extracting VBA Blobs
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-25 19:57:03 +00:00
										 |  |  | To extract blobs, `bookVBA: true` must be set in the `read` or `readFile` call. | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The following example extracts the embedded VBA blob in a workbook: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <Tabs groupId="platform"> | 
					
						
							|  |  |  |   <TabItem value="browser" label="Web Browser"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSExtractVBA(props) { | 
					
						
							|  |  |  |   const [msg, setMsg] = React.useState("Select a macro-enabled file"); | 
					
						
							|  |  |  |   return ( <> | 
					
						
							|  |  |  |     <b>{msg}</b><br/> | 
					
						
							|  |  |  |     <input type="file" onChange={async(e) => { | 
					
						
							|  |  |  |       /* parse workbook with bookVBA: true */ | 
					
						
							|  |  |  |       const wb = XLSX.read(await e.target.files[0].arrayBuffer(), {bookVBA: true}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* get vba blob */ | 
					
						
							|  |  |  |       if(!wb.vbaraw) return setMsg("No VBA found!"); | 
					
						
							|  |  |  |       const blob = wb.vbaraw; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* download to vbaProject.bin */ | 
					
						
							|  |  |  |       setMsg("Attempting to download vbaProject.bin"); | 
					
						
							|  |  |  |       const url = URL.createObjectURL(new Blob([blob])); | 
					
						
							|  |  |  |       const a = document.createElement("a"); | 
					
						
							|  |  |  |       a.download = "vbaProject.bin"; a.href = url; | 
					
						
							|  |  |  |       document.body.appendChild(a); a.click(); | 
					
						
							|  |  |  |       document.body.removeChild(a); | 
					
						
							|  |  |  |     }}/> | 
					
						
							|  |  |  |   </> ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  |   <TabItem value="nodejs" label="NodeJS"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 0) Install the dependencies: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <CodeBlock language="bash">{`\ | 
					
						
							|  |  |  | npm init -y | 
					
						
							|  |  |  | npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} | 
					
						
							|  |  |  | </CodeBlock> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Save the following script to `extract_vba.js`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js title="extract_vba.js" | 
					
						
							|  |  |  | const fs = require("fs"), XLSX = require("xlsx"); | 
					
						
							|  |  |  | const wb = XLSX.readFile(process.argv[2], { bookVBA: true }); | 
					
						
							|  |  |  | if(!wb.vbaraw) throw new Error("Could not find VBA blob!"); | 
					
						
							|  |  |  | fs.writeFileSync("vbaProject.bin", wb.vbaraw); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2) Run the script: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | node extract_vba.js SheetJSMacroEnabled.xlsm | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This script will generate `vbaProject.bin`. It can be added to a new workbook. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </TabItem> | 
					
						
							|  |  |  | </Tabs> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Exporting Blobs
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To ensure the writers export the VBA blob: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - The output format must support VBA (`xlsm` or `xlsb` or `xls` or `biff8`) | 
					
						
							|  |  |  | - The workbook object must have a valid `vbaraw` field | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | - The option `bookVBA: true` must be passed to `write` or `writeFile` | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | This example uses [`vbaProject.bin`](pathname:///vba/vbaProject.bin) from the | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | [sample file](pathname:///vba/SheetJSVBAFormula.xlsm). When the files are | 
					
						
							|  |  |  | opened, if macros are enabled, the application will display a popup. | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | :::note pass | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | Cells `A2:C2` in the worksheet include formulae that use user-defined functions. | 
					
						
							|  |  |  | Not all file formats support formula exports. [The "Formulae" page](./formulae) | 
					
						
							|  |  |  | includes a table of supported file formats. | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | ::: | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-04 03:55:16 +00:00
										 |  |  | ```jsx live | 
					
						
							|  |  |  | function SheetJSVBAPrepared() { | 
					
						
							|  |  |  |   const exportFile = async (ext) => { | 
					
						
							|  |  |  |     /* Download prepared VBA blob */ | 
					
						
							|  |  |  |     const url = "/vba/vbaProject.bin"; | 
					
						
							|  |  |  |     const blob = new Uint8Array(await (await fetch(url)).arrayBuffer()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* generate worksheet and workbook */ | 
					
						
							|  |  |  |     const worksheet = XLSX.utils.aoa_to_sheet([ | 
					
						
							|  |  |  |       ["Cell", "A1", "RC"], | 
					
						
							|  |  |  |       [ | 
					
						
							|  |  |  |         {t:"n", f:"LEN(A1)"},      // A2 | 
					
						
							|  |  |  |         {t:"s", f:"GetFormulaA1(A2)"},  // B2 | 
					
						
							|  |  |  |         {t:"s", f:"GetFormulaRC(A2)"}   // C2 | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |     const workbook = XLSX.utils.book_new(); | 
					
						
							|  |  |  |     XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* add VBA blob to new workbook */ | 
					
						
							|  |  |  |     workbook.vbaraw = blob; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* export data to the specified file format */ | 
					
						
							|  |  |  |     XLSX.writeFile(workbook, `SheetJSVBAPreparedNeu.${ext}`); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ["xlsm", "xlsb", "xls"].map((ext) => ( <> | 
					
						
							|  |  |  |     <button onClick={() => exportFile(ext)}> | 
					
						
							|  |  |  |       <b>Click to Generate {ext.toUpperCase()}!</b> | 
					
						
							|  |  |  |     </button> | 
					
						
							|  |  |  |     <br/> | 
					
						
							|  |  |  |   </> )); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-05-23 18:53:11 +00:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Details
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Code Names
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Excel will use `ThisWorkbook` (or a translation like `DieseArbeitsmappe`) as the | 
					
						
							|  |  |  | default Code Name for the workbook.  Each worksheet will be identified using the | 
					
						
							|  |  |  | default `Sheet#` naming pattern even if the worksheet names have changed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A custom workbook code name will be stored in `wb.Workbook.WBProps.CodeName`. | 
					
						
							|  |  |  | For exports, assigning the property will override the default value. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Worksheet and Chartsheet code names are in the worksheet properties object at | 
					
						
							|  |  |  | `wb.Workbook.Sheets[i].CodeName`.  Macrosheets and Dialogsheets are ignored. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The readers and writers preserve the code names, but they have to be manually | 
					
						
							|  |  |  | set when adding a VBA blob to a different workbook. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### Macrosheets
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Older versions of Excel also supported a non-VBA "macrosheet" sheet type that | 
					
						
							|  |  |  | stored automation commands.  These are exposed in objects with the `!type` | 
					
						
							|  |  |  | property set to `"macro"`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Under the hood, Excel treats Macrosheets as normal worksheets with special | 
					
						
							|  |  |  | interpretation of the function expressions. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #### Detecting Macros in Workbooks
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The `vbaraw` field will only be set if macros are present.  Macrosheets will be | 
					
						
							|  |  |  | explicitly flagged.  Combining the two checks yields a simple function: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```js | 
					
						
							|  |  |  | function wb_has_macro(wb/*:workbook*/)/*:boolean*/ { | 
					
						
							|  |  |  |   if(!!wb.vbaraw) return true; | 
					
						
							|  |  |  |   const sheets = wb.SheetNames.map((n) => wb.Sheets[n]); | 
					
						
							|  |  |  |   return sheets.some((ws) => !!ws && ws['!type']=='macro'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` |