Utilizing a 2D array that has been downloaded previously and reusing it as a 2D array once more

I am working with a 2D array in JavaScript within a Google Chrome extension. Each index contains text with various characters. I have successfully converted this 2D array into a CSV file and provided code for downloading it:

function Download(){
  //https://stackoverflow.com/a/14966131/11974735
  var array = JSON.parse(sessionStorage.getItem("array"));
  let csvContent = "data:text/csv;charset=utf-8," 
    + array.map(e => e.join(",")).join("\n");
  var encodedUri = encodeURI(csvContent);
  var link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", "my.csv");
  document.body.appendChild(link); // Required for FF
  link.click();
}
// This will download the data file named "my_data.csv".

Now, my challenge is how to upload and utilize this as a 2D array again (on another machine or in case of hard drive crash)? Upon researching online, I found solutions where the file cannot contain specific characters due to delimiter issues, among other complications.

If anyone could assist me, I would greatly appreciate it.

This simple solution may encounter difficulties if the cells contain quotes, commas, or other escaped characters. To handle more complex CSV strings, a Regex solution would need to be implemented (refer to the accepted answer on "How can I parse a CSV string with Javascript?"). Alternatively, using a library would be more efficient to support multiple common formats.

Answer №1

Using JSON.stringify allows us to generate CSV line strings, and using JSON.parse enables us to restore the data back to its original state.

For example:

var a = ["abc", '"', "'", ","];
var csv = JSON.stringify(a);     // format any symbols properly
console.log(csv);                // ["abc","\"","'",","]
csv = csv.slice(1, -1);          // remove the square brackets
console.log(csv);                // "abc","\"","'",","
csv = csv.replace(/\\"/g, '""'); // replace \" with ""
console.log(csv);                // "abc","""","'",","

The code below demonstrates how to download data as a CSV file from sessionStorage, upload the file, and then store it back into the sessionStorage.

<html>
<head>
  <meta charset="utf-8" />
</head>
<body>
<script>

storeData(); // initially store data, for download

function storeData() {
  var array = JSON.stringify([
    ["lorem", "symbols\"',\n!@#$%^&*()_+-={}|[]:;<>/?", 'ip"sum'],  // any symbols
    ["hello", "emoji⌚⌛⏩", "world"],  // any emojis
  ]);
  sessionStorage.setItem("array", array);
}

function Download() {
  var array = JSON.parse(sessionStorage.getItem("array"));
  var csvContent = array.map(e => JSON.stringify(e).slice(1, -1).replace(/\\"/g, '""')).join("\n");
  var encodedUri = "data:text/csv;charset=utf-8," + encodeURIComponent(csvContent);
  var link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", "my.csv");
  document.body.appendChild(link); 
  link.click();
}

function Upload() {
  var file = document.getElementById("fileForUpload").files[0];
  if (file) {
    var reader = new FileReader();
    reader.readAsText(file, "UTF-8");
    reader.onload = function (evt) {
      var array = convertCsvToArray(evt.target.result);       
      sessionStorage.setItem("array", JSON.stringify(array));
    }
    reader.onerror = function (evt) {
      console.log("error reading file");
    }
  }
}

function convertCsvToArray(csvStr) {
  return csvStr.split(/\n/).map(line => { 
    var items = Array.from(
      line.matchAll(/("(([^"]|"")*?)"|([^",][^,]*?))?(,|$)/g)
    ).map(match => match[2] || match[4] || ''); 

    var jsonStr = '[' + items.slice(0, -1).map(item => '"' + item.replace(/""?/g, '\\"') + '"').join(",") + ']';

    return JSON.parse(jsonStr);
  });
}

</script>
  <button onclick="Download()">Download</button>
  <input type="file" id="fileForUpload">
  <button onclick="Upload()">Upload</button>
</body>
</html>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm looking for ways to incorporate TypeScript definition files (.d.ts) into my AngularJS application without using the reference path. Can anyone provide

I'm interested in leveraging .d.ts files for enhanced intellisense while coding in JavaScript with VScode. Take, for instance, a scenario where I have an Angular JS file called comments.js. Within comments.js, I aim to access the type definitions prov ...

Display a form with hidden input that dynamically updates on any input change

<form id="pricecal"> <input type="text" onchange="calprice()" class="form-control round-corner-fix datepicker" data-provide="datepicker" placeholder="Check in" value="" required /> <input type="text" onchange="calprice()" class="form ...

Having trouble with React button conditional rendering not functioning properly

Currently, I am working on a cart application and facing an issue. The problem is that the button is not getting disabled when the quantity reaches zero. Instead, it continues to show the 'add to cart' button even when no items are left in stock. ...

Learn how to incorporate a click event with the <nuxt-img> component in Vue

I am encountering an issue in my vue-app where I need to make a <nuxt-img /> clickable. I attempted to achieve this by using the following code: <nuxt-img :src="image.src" @click="isClickable ? doSomeStuff : null" /> Howeve ...

Encountering difficulties while trying to install ng2-material in Angular 2

I'm attempting to utilize a data table with the ng2-material library from ng2-material as shown below: <md-data-table [selectable]="true"> <thead> <tr md-data-table-header-selectable-row> <th class="md-text-cell">M ...

Issue: App is not being styled with Material UI Theme Colors

I'm having trouble changing the primary and secondary colors of Material UI. Even after setting the colors in the theme, the controls like Buttons or Fabs still use the default colors. Can someone help me figure out what I'm missing? index.js /* ...

The error "map is not a function" occurs when trying to update the

I've encountered an issue with my links rendering on a page. I wrote a function that toggles a specific property from false to true based on whether the link is active or not, triggered by a click event. Upon inspecting the updated set of links, I no ...

Arrays causing Typescript compilation errors

There are a pair of typescript documents: one file as a module that implements the Client class export class Client { the other file as the main document that imports the module and generates an array of clients import c = module("client ...

Having trouble accessing the ng-model within ng-repeat in the controller of an AngularJS component

One approach I am considering is to use ng-model="model.ind[$index]" in order to keep track of the active tag. This way, when I click on a tag (specifically the 'a' tag), both the parentIndex and $index will be passed to my controller. Subsequent ...

Repeat the most recent AJAX request executed

I am currently working on refreshing a specific section of my application which is generated by an AJAX call. I need to target the most recent call that was made and rerun it with the same parameters when a different button is clicked. The data was initial ...

What is the best method for extracting an array item from a delimited string?

Here is an example of a multidimensional array: array('csv'=> array('path'=>'/file.csv', 'lines'=>array('line1', 'line2', ...

I am interested in using the split method to separate and then mapping an object in JavaScript

Need assistance on separating an array using the split method. The array contains objects with properties such as name, course1, course2, and course3. Only the courses with text in their content along with a plus sign should be separated into an array usin ...

Stop procrastinating and take action before the JavaScript function concludes

Currently, I am experimenting with onkeydown events to capture the input value in a textarea, process it through a PHP file using Ajax post method, and display the result in an external div. However, the issue is that whenever a key is pressed, I am unable ...

Using PHP to filter data using $_GET variables?

https://i.sstatic.net/vDqe3.png In order to sort the small divs based on specific filters like AB Main Hall, AB Club, Huis 23, I believe using $_GET is necessary. Here is the code snippet I currently have. <?php $concert = [ [ "datum" =& ...

Using various conditions and operators to display or conceal HTML elements in React applications, particularly in NextJS

I am seeking ways to implement conditional logic in my React/Next.js web app to display different HTML elements. While I have managed to make it work with individual variable conditions, I am encountering difficulties when trying to show the same HTML if m ...

Can the arrangement of icons/buttons on the JW Player control bar be customized?

I am trying to customize the skin of my JWplayer like this: This is my current progress: I have been researching how to rearrange the order of icon / button on the controlbar. According to the jwplayer documentation, the buttons on the controlbar are div ...

ShaderMaterial does not support textures when replicating MeshLambertMaterial

It came to my attention that THREE.js utilizes shaders internally for creating core material like "e.g. MeshLambertMaterial". Intrigued by this, I decided to replicate the lambert shader from Three.js code into a new shader and expand upon it. Below is th ...

Running NPM module via Cordova

After developing an app using cordova, I encountered a challenge where I needed to incorporate a node module that lacked a client-side equivalent due to file write stream requirements. My solution involved utilizing Cordova hooks by implementing an app_run ...

Update the value of input within a Struts2 iterator by utilizing JavaScript

As a junior programmer, I am trying to update the value of an input type text within a Struts2 iterator without refreshing the entire page. I believe using JSON could be a solution for this issue. Here is my JSP code: <input type="text" name="cantidad ...

The URL remains unchanged even after clicking the search button using the post method

Whenever I visit a page with URL parameters, such as , and perform a search using the search button with form method = post, the URL maintains the previous parameter values even after displaying the search results. Even though it shows the search result, ...