Can/will Datacore be able to read CSV?

I don’t see anything mentioning it on the overview of Datacore, so I’m wondering if I missed it, or if this is something that won’t be moved over from Dataview. I use it in Obsidian specifically to get data from a csv file (as my other program gives me my compiled data that way), and it would be a bummer if datacore didn’t work.

And if not, I don’t mind using Dataview, but what are the chances of that being discontinued or breaking? I have ideas for a whole set up, but I’m a bit worried that after I implement it, it’ll stop working.

Dataview and Datacore can both be used with Javascript so the answer is yes.
As for what breaks and when, nobody knows.
As long as the metadatacache API is not changed, we’re supposed to be good, as far as I know.

1 Like

I’ll try to keep dataview up and running, as long there are not major breakage arising from other Obsidian development, and I’m not to busy with real life.

Can I guarantee for how long? No, but that we don’t know for any of the plugins (or not really for the main code of Obsidian either). Life happens, and things change.

And I reckon that Datacore will support CSV-files at some n point, if not already supported. Dataview do definitely support it, and there also other plugins supporting it to some degree.

1 Like

If concerned about the shelf life of community plugins, perhaps the upcoming core plugin Dynamic Views—which presumably will be supported for as long as Obsidian is maintained—would be a safer bet.

2 Likes

I’ve been using Datacore to load CSV files into a component, and it works well enough for my needs right now.

In case it’s useful, here’s a simple example of how I’m handling CSV data inside a custom component. I just read the file from the vault, parse it, and convert the headers into camelCase keys so I can work with them more easily.

const { useEffect, useState } = dc;

function toCamelCase(str) {
  return str
    .toLowerCase()
    .replace(/[^a-zA-Z0-9 ]/g, '')
    .replace(/ ([a-z])/g, (_, letter) => letter.toUpperCase())
    .replace(/^([A-Z])/, (_, letter) => letter.toLowerCase());
}

return function CsvViewer() {
  const [data, setData] = useState([]);

  useEffect(() => {
    const loadCsv = async () => {
      const filePath = "data/asdf.csv";
      const file = app.vault.getAbstractFileByPath(filePath);

      if (!file) return console.error("File not found:", filePath);

      const content = await app.vault.read(file);
      const lines = content.split('\n').filter(line => line.trim() !== '');
      const rows = lines.map(line => line.split(',').map(cell => cell.trim()));

      if (rows.length < 2) return;

      const headers = rows[0].map(toCamelCase);
      const objects = rows.slice(1).map(row =>
        Object.fromEntries(headers.map((key, i) => [key, row[i] || ""]))
      );

      setData(objects);
      console.log(objects); // for dev
    };

    loadCsv();
  }, []);

  return (
    <table>
      <thead>
        <tr>
          {data.length > 0 &&
            Object.keys(data[0]).map((key, index) => (
              <th key={index}>{key}</th>
            ))}
        </tr>
      </thead>
      <tbody>
        {data.map((row, rowIndex) => (
          <tr key={rowIndex}>
            {Object.values(row).map((value, colIndex) => (
              <td key={colIndex}>{value}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

So far, this approach is working fine for reading basic CSV logs (in my case, exported time entries). Not sure how future-proof this is, but it gets the job done for now.

In addition to the methods mentioned above, another approach is to register a function in customJS to process CSV files.

(system/script/csv.js)

class CSV {
  async load(path) {
    const file = app.vault.getAbstractFileByPath(path);
    if (!file) {
      console.error('File not found:', path);
      return [];
    }

    const content = await app.vault.read(file);
    const lines = content.split('\n').filter(line => line.trim() !== '');
    const rows = lines.map(line => line.split(',').map(cell => cell.trim()));

    if (rows.length < 2) {
      console.warn('CSV has insufficient rows:', path);
      return [];
    }

    const headers = rows[0].map(CSV.toCamelCase);

    const data = rows
      .slice(1)
      .map(row => Object.fromEntries(headers.map((key, i) => [key, row[i] || ''])));

    return data;
  }

  static toCamelCase(str) {
    return str
      .toLowerCase()
      .replace(/[^a-zA-Z0-9 ]/g, '')
      .replace(/ ([a-z])/g, (_, letter) => letter.toUpperCase())
      .replace(/^([A-Z])/, (_, letter) => letter.toLowerCase());
  }
}

(Usage example)

const { CSV } = await cJS()
const data = await CSV.load('path-to-csv.csv')

Hope this helps!