Write_Table v2
SEE UPDATE BELOW for new node and module names...
Almost 10 years ago I created a node called write_table that, when rendered, would write a CSV file:
http://support.nodebox.net/discussions/show-your-work/183-write_tab...
This was before Frederik added the ability to export CSV files; in fact this node helped persuade him to do that. Once that export option was added, there was almost no need for my original write_table node.
Almost.
Turns out it is still useful for some unusual situations:
- Creating and then reading a file repeatedly as part of some process like Conways's Game of Life (see http://support.nodebox.net/discussions/show-your-work/173-conways-g...)
- Dividing a table into sub-tables and then automatically saving all of them with individual names
- Writing hundreds of kodi media stub text files (mentioned in conversation thread above)
- Creating a set of interlocking html files
I recently needed to do the last example and found that my old write_table node needed a few modifications. The original node took tables as an input, but for HTML files I wanted to just give it lines of text with no table headers. I also needed a cleaner way to create multiple HTML files named in a particular way. Hence, write_table V2.
Write_table now takes the following inputs:
- Data. Can now be either a table or a list. If a table, the output file will include headers; if a list, it will not.
- Directory. A file path to a directory. This field uses the file widget which lets you browse to any directory. But since the file widget forces you select a file, you will need to point to a directory with at least one file in it. The file itself doesn't matter; its only purpose is to define the directory.
- File Name. The name of your new file, which normally includes a file extension (e.g. hello.html, read me.txt, data.csv, etc.). This file name will be appended to the directory path you identified.
- Delimiter. Only needed when saving CSV files; ignored when you pass a list as data. The default comma works for most situations, but some other delimiter may be needed when the table cells contain commas.
When this node is rendered, it will save the file and, if no errors occur, return a "{filename} Saved" message. If you feed it multiple file names, it will return a separate message for each file created.
Note. If you are using this node as part of a larger process which involves writing and then reading these files, you will need to force this node to render. One way of doing this is to feed a downstream node and the write_table node into a switch node with the switch set to 0. This will pass the node you want further downstream while also forcing the write_table node to silently fire.
The attached demo shows two use cases.
Case 1. I create a fake table with data for two countries, Brazil and India. I then feed this into a separate_CSV subnetwork which filters the data by country and then creates a separate CSV for each country in the dataset. Look inside the subnetwork to see the write_table node. The node identifies a test folder which contains a dummy.txt file; you can select dummy.txt with the Directory file widget to identify that directory. Once you render the separate_CSV subnetwork you will see two file saved messages. The two import_csv nodes below can then be used to view each of the two CSV files created.
Case 2. I create a dummy HTML file with a make_strings node, create 3 file names with a range node, the feed them into a write_table node to create three identical HTML files with individual names inside the same test folder. The screenshot shows the 3 messages produced when the node is rendered. You can open any one of the HTML files in a browser to see that they work. This example creates three identical HTML files. In most situations you would modify the template to create a different web pages for each file name. Note that because we are feeding in a list of strings instead of a table, the resulting HTML files have just the template text with no headers.
The zip file includes a folder with the demo, the new Python file, and a sub-folder with a dummy file.
This node requires a NEW version of the external write_table module, now called write_table_v2. You will need reference this module in your code Library to use the new node. If you look at the Python code inside that module, you will see that I also improved how the file path gets resolved. If you need to pass file paths to your own modules, this can serve as an example.
If ANYONE see this note, and actually has a use case for this unusual node, please let me know!
-
write_table_screenshot.png
406 KB
- write_table_v2.zip 47.4 KB
Keyboard shortcuts
Generic
| ? | Show this help |
|---|---|
| ESC | Blurs the current field |
Comment Form
| r | Focus the comment reply box |
|---|---|
| ^ + ↩ | Submit the comment |
You can use Command ⌘ instead of Control ^ on Mac
Support Staff 1 Posted by john on 17 Aug, 2026 04:27 AM
UPDATE!
Seconds after publishing the above node, I realized that now that it takes lists as well as tables, I should rename the node and the external module. Which I have done.
So now the node is called write_file and the module is called write_file.py.
Everything else works as before. New files attached.
2 Posted by indefiniteness on 05 Sep, 2026 12:56 PM
Interesting. Yes, this is the type of logic that could be useful for implementing the approach I used for multi-state functions in my JS codebase inside of NodeBox.
I think some of the nuances in your approach actually simplifies something that was hard to solve in my JS project too. That is, creating a program that is reactive without having to have a script running in a loop as a background process in order to detect the intended triggers for some arbitrary next step.
Also, the original JS project has a declarative development interface that is meant to leverage this reactivity to work on the codebase itself as a declarative table that is populated by one of each individual code elements (variables, function definitions, import/export, etc etc). Then, there are some cells that are 'computed groups' that automatically update the entire codebase when an update has been made to one of the individual code elements, new code elements are added to the codebase, from the 'single source of truth' for that respective element's defined cell in the table.
The reactivity automatically keeps the entire codebase in sync based on the original cell where a code element is defined using the 'computed groups' using logic like one would in an Excel spreadsheet - using a simple formula to build the necessary functionality or logic from each of the code elements by simply pointing to the cell location in the table. The need for import/export statements and/or handling of dependencies actually becomes irrelevant this way also. Just 'import' a dependency by defining this functionality in a dedicated cell... the 'computed groups' combine the necessary elements from where they are defined, as well as, pushes or pulls the required imports or exports in the same way.
The code actually executes its own functionality as it is being developed, automatically, and without actually needing to have script looping as a background process - which is the very obstacle to being able to do this.
---
But that is just part of it...
The project I was actually working on which required my to need to come up with all of the above can do lots more using the approach you've taken for write_table_v2.