DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

Electron Adventures: Episode 88: Svelte CSV Viewer

I want to experiment with a few interesting OS integrations, but first let's get an app for that - a simple CSV viewer is Svelte.

When you start the app, it will open a file dialog and ask you to select one or more CSV files to open. Then it will open a new window for each selected file.

I picked a few CSV example files with Taylor Swift lyrics from Kaggle and put them into samples subfolder.

I'll be using d3-dsv to parse CSV files. It's part of the D3, but it can be used separately, so npm install d3-dsv.


First, we need to popup the dialog to select the CSV files.

let { app, BrowserWindow, dialog } = require("electron")

async function createWindow() {
  let { canceled, filePaths } = await dialog.showOpenDialog({
    properties: ["openFile", "multiSelections", "showHiddenFiles"],
    filters: [
      { name: "CSV files", extensions: ["csv"] },
      { name: "All Files", extensions: ["*"] }
    message: "Select a CSV file to open",
    defaultPath: `${__dirname}/samples`,
  if (canceled) {
  for (let path of filePaths) {
    let qs = new URLSearchParams({ path }).toString();
    let win = new BrowserWindow({
      width: 1024,
      height: 768,
      webPreferences: {
        preload: `${__dirname}/preload.js`,

app.on("ready", createWindow)

app.on("window-all-closed", () => {
Enter fullscreen mode Exit fullscreen mode

As I mentioned before, this is Electron API weirdness. File dialogs are really a frontend concern, so logically they should go to the frontend process, but Electron API moves them to the backend, so we have to jump through a few hoops here.

For a small change from the hex editor, we setup default filter to only show *.csv files, it can be overridden by the user through the OS-specific filter dropdown.


let fs = require("fs")
let { contextBridge } = require("electron")

let q = new URLSearchParams(

let path = q.get("path")
let data = fs.readFileSync(path, "utf8")

  "api", { path, data }
Enter fullscreen mode Exit fullscreen mode

A small change from the hex editor, we want to return a String, not a Buffer, so we assume CSV is in UTF8. If it's not, well, it's 21st century, you should have fixed that already.


And now for a very simple CSV viewer - we just dump everything into a simple HTML table, with no special handling of headers, or data types, or anything.

  import {csvParseRows} from "d3-dsv"

  let data = csvParseRows(
  let fileName = window.api.path.split("/").slice(-1)[0]
  let title = `CSV Viewer - ${fileName}`

<h1>CSV Viewer</h1>

  {#each data as row}
      {#each row as column}


:global(body) {
  margin: 0;
  background-color: #444;
  color: #fff;
tr {
  text-align: center;
Enter fullscreen mode Exit fullscreen mode


Here's the results:

Episode 88 Screenshot

Now that we have a base app, we'll be adding a few interesting enhancements to it over the next few episodes.

As usual, all the code for the episode is here.

Top comments (0)