Export Dataview tables to CSV with DataviewJS

Continuing the discussion from Dataview - Exporting Table as CSV and based on my answer to another post here, I’ve come up with an imperfect way to save dataview tables as csv fies, if that’s something you’d find useful.

This code does the following:

  1. Grab the data you want
  2. Select the columns you want in the table
  3. Export the table as a CSV file

Example

Note: dataviewjs must be appended for code block

// ----- Gather data and specify table columns -----
// Grab all relevant notes/pages
let projects = dv.pages("#projects");
// Grab the columns you want using .map function
const projects_tbl = projects.map(p => [p.file.link,p.status,p.domain]);
// Map function traverses each row and joins elements with ",", then we join the array of strings with "\n"
let csvContent = "data:text/csv;charset=utf-8," + projects_tbl.map(e => e.join(",")).join("\n");

// ------ Create CSV file ------
// Create a hidden <a> DOM node and set its download attribute as follows, where "my_data.csv" will be the name of your csv file
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download","my_data.csv");
document.body.appendChild(link);
link.click();

I would use this at your discretion, as it uses some functions I am unaware of, but suffice to say I’ve tested this and I got a table just as I wanted, as a csv file. Once this code has run, it will automatically bring up a window to save the file, and bear in mind that this will keep running if you have set dataview queries to re-evaluate in Live-Preview. So, I would run it as a script perhaps?

Would love some extra suggestions to improve upon this to make it:

  • More succinct
  • More flexible
  • Edit: header info would be nice too

Generalisable version here:

// ----- Gather data and specify table columns -----
// Grab all relevant notes/pages
let <name_of_pages> = dv.pages("<source>");
// Grab the columns you want using .map function
const <table_name> = <name_of_pages>.map(p => [p.<field1>,p.<field2>,p.<field3>]);
// Map function traverses each row and joins elements with ",", then we join the array of strings with "\n"
let csvContent = "data:text/csv;charset=utf-8," + <table_name>.map(e => e.join(",")).join("\n");

// ------ Create CSV file ------
// Create a hidden <a> DOM node and set its download attribute as follows, where "my_data.csv" will be the name of your csv file
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download","<csv_file_name>.csv");
document.body.appendChild(link);
link.click();

Is this going to get any table on the page? How I can set it up? Or just put it in a Templater and run it?

Hi @Archie.

The JavaScript in my example is not actually grabbing any table on the page in this instance
This part of the code is the source of the data:

This part of the code determines the fields/attributes from said pages that will populate the table

You could run this code alongside rendering it, if you simply added code to render the same table like so:

const headers = ["Field 1", "Field 2", "Field 3"]
const elements = dv.pages("<source>").map(p => [p.<field1>,p.<field2>,p.<field3>]);
dv.table(headers, elements);

I’ve tried to present the most bare-bones way to achieve this goal, but I suspect a good way to do it might be an actual button that runs the code using the buttons plugin.

Again, this could do with more work, but I imagine having:

  • Templater plugin
  • Dataview plugin
  • Buttons plugin

And then:

  • Having a button;in the file that you want a csv for, perhaps on a regular basis;that links to a template
  • A templater template that simply runs the code I have written above

Thank you , I agree that Buttons and Templater is the way to go to run it regularly. But I don’t still get it. How it is going to identify tables if (i don’t know any identifiers or name for them in dv code. I just use normal basic dataview code blocks. Should I put the table columns by their name (after AS ) or the variable linked to it.

Ah okay, I’ll explain the two concepts in parallel, with the same references in both cases:

Normal Dataview query

TABLE
    field2 AS "Field 2",
    field3  AS "Field 3"
FROM <source>

DataviewJS to export equivalent table as CSV

let source = dv.pages("<source>");
const table = source.map(p => [p.<field1>,p.<field2>,p.<field3>]);
let csvContent = "data:text/csv;charset=utf-8," + table.map(e => e.join(",")).join("\n");
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download","my_data.csv");
document.body.appendChild(link);
link.click();

Both can have optional WHERE conditions.

Finally, to make it clear, the Dataview code block as you are familiar with starts with ```dataview, and the DataviewJS code block starts with ```dataviewjs

3 Likes

Oh I see, so you making a table and exporting it at the same time, which makes sense. Thanks for clarifying it for me, I have very little experience with dataviewjs so far

2 Likes