Synthoid / ExportSheetData

Add-on for Google Sheets that allows sheets to be exported as JSON or XML.
MIT License
236 stars 46 forks source link

Error on export #93

Open Sandstedt opened 5 years ago

Sandstedt commented 5 years ago

Tried to export a sheet as usual, same sheet that has worked before. But today I got this error in Chrome:

Uncaught  at exportDocument (ExportSheetData:1797) (Export Sheet Data:54) 9424292d-7319-4278-867f-12dda0a70ec3
 at exportSpreadsheetJson (ExportSheetData:1687) (Export Sheet Data:54) 9424292d-7319-4278-867f-12dda0a70ec3
 at exportJson (ExportSheetData:677) (Export Sheet Data:54) 9424292d-7319-4278-867f-12dda0a70ec3

gp { message: "There was an error during the transport or process…this request. Error code = 10, Path = /wardeninit", name: "TransportError", stack: "TransportError: There was an error during the tran…2496433205-warden_bin_i18n_warden__sv.js:189:252 }

And in Firefox:

Error: Access denied: DriveApp.
Sandstedt commented 5 years ago

Created a small app to do similar things that I used this plugin for, if anyone is interested: https://google-sheet-data.jonassandstedt.now.sh/ - Repository

Copy this code and save as a html file and run on a server, or locally using something like live-server.

The options I have is that you can create arrays in cells with ", " seperating the items: Item1, Item2, Item3

If you need a comma in the text cell and don't want to get an array, wrap them in quotes: "Some text, with a comma".

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Datafetching from Google Drive</title>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"
    integrity="sha256-XmdRbTre/3RulhYk/cOBUMpYlaAp2Rpo/s556u0OIKk=" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <link rel="stylesheet" href="https://unpkg.com/purecss@1.0.1/build/pure-min.css"
    integrity="sha384-oAOxQR6DkCoMliIh8yFnu25d7Eq/PHS21PClpwjOTeU2jRSq11vu66rf90/cZr47" crossorigin="anonymous">

  <style>
    .language-css {
      user-select: all;
    }

    .content {
      margin-left: auto;
      margin-right: auto;
      padding-left: 1em;
      padding-right: 1em;
      max-width: 768px;
    }
  </style>
</head>

<body>
  <div id="app" class="content">
    <h1 style="text-align: center">Google Sheet Data Fetch</h1>
    <form class="pure-form pure-form-aligned">
      <fieldset>
        <div class="pure-control-group">
          <label for="sheet_id">Sheet id</label>
          <input id="sheet_id" v-model="sheet_id">
          <span class="pure-form-message-inline">(<a
              href="https://docs.google.com/spreadsheets/d/[sheetid]/edit#gid=xxxx">Example</a>)</span>
        </div>
      </fieldset>

      <fieldset>
        <div class="pure-control-group">
          <label for="api_key">API key</label>
          <input id="api_key" v-model="api_key">
          <span class="pure-form-message-inline">(<a
              href="https://console.developers.google.com/apis/credentials">create here</a>)</span>
        </div>
      </fieldset>

      <fieldset>
        <div class="pure-control-group">
          <label for="ranges">The sheets to fetch data from:</label>
          <input id="ranges" v-model="ranges">
          <span class="pure-form-message-inline">(ex: ranges=sort&ranges=multichoice&ranges=yesno)</span>
        </div>
      </fieldset>

      <div class="pure-controls">
        <p><small>Make sure the Google Sheet has share settings of "Everyone with the link can show".</small></p>
        <button type="button" v-on:click="fetchData" class="pure-button pure-button-primary">Fetch Data</button>
      </div>
    </form>

    <section>
      <div v-if="fetching">Fetching data...</div>

      <div v-if="error">
        <h3>Something went wrong</h3>
      </div>

      <div v-if="loaded" class="data">
        <p>Check your console, or copy data from here:</p>
        <pre>
<code class="language-css">
{{ this.info }}
</code>
        </pre>
      </div>

    </section>
  </div>

  <script>
    new Vue({
      el: '#app',
      data() {
        return {
          info: null,
          fetching: false,
          loaded: false,
          errored: false,
          sheet_id: 'xxxxxx-xxxxxxxxxxxxxxxx',
          api_key: 'xxxxxxxxxxxxxxxxxxxxxx-x',
          ranges: 'ranges=sort&ranges=multichoice&ranges=yesno&ranges=chooseimage&ranges=pair',
        }
      },
      methods: {
        fetchData: function () {
          this.fething = true;

          const SHEET_ID = this.sheet_id;
          const API_KEY = this.api_key;
          const RANGES = this.ranges;
          axios            
            .get(`https://sheets.googleapis.com/v4/spreadsheets/${SHEET_ID}/values:batchGet?${RANGES}&key=${API_KEY}`)

            .then((response) => {

              const data = response.data.valueRanges;
              const formatedData = data.map(sheet => {
                let values = sheet.values; // all the values
                const keys = values.shift(); // remove the first array item, this is the keys for the object

                // map the values to the keys
                values = values.map(valueWrap => {
                  let obj = {};
                  keys.forEach((key, index) => {
                    let str = valueWrap[index]; // the data from a single cell
                    const isArray = /[,\/]/g.exec(str);
                    const isString = /"/g.exec(str); // Wrap a string to prevent a array detection below

                    if (isArray && !isString) {
                      str = str.split(", ");
                    }
                    // Boolean converter (when using google sheets boolean data types )
                    if (str === 'TRUE') str = true;
                    if (str === 'FALSE') str = false;

                    obj[key] = str; // add that data to the object
                  });
                  return obj;
                });
                return {
                  sheet: sheet.range,
                  keys: keys,
                  values: values,
                }
              })
              arrWithAllItems = [];
              formatedData.forEach(sheet => {
                arrWithAllItems.push(...sheet.values);
              });
              console.log('data', arrWithAllItems);

              this.info = arrWithAllItems;
            })
            .catch((error, message) => {
              console.log(error)
              this.errored = true
              this.info = { error: error, message: message };
            })
            .finally(() => {
              this.fething = false;
              this.loaded = true;
            })
        }
      },
      mounted() {

      }
    })
  </script>

</body>

</html>
Synthoid commented 5 years ago

Sorry for the delayed response! What settings were you using?

Flazone commented 5 years ago

Hi, I got the same error here, I can't export my XML anymore.

Here are my settings: export options

Synthoid commented 5 years ago

Hmm, can you link an example sheet? It's possible there's an edge case for special characters in the data that causes some issue.

Sandstedt commented 5 years ago

Could it be that the sheets is private in a G suite environment? This document works fine: https://docs.google.com/spreadsheets/d/15_4BWf1UIexlnh4qXlYcT89LgQIXHl-HlXYM0d55xRg/

But the similar document with the same settings that is private in a G Suite corporate environment doesn't work.

Flazone commented 5 years ago

Hmm, can you link an example sheet? It's possible there's an edge case for special characters in the data that causes some issue.

I don't use any special characters, the same sheet was working fine 1 week ago :/

I'm using a private G suite environment, so I tried to copy the same sheet into my personal space and it's working fine.

Synthoid commented 5 years ago

Hmm. An interesting possibility. When installing ESD you agree to give it permission to control your DriveApp functions for reading and exporting data. That allows ESD to function with private sheets on standard accounts, but maybe G Suite's tighter controls are causing issues? If so, that'll be a fun issue to track down and solve. I'll try exporting various sheets from my G Suite account later today. A quick test of a private sheet shared with my G Suite account seemed to export fine.

As a quick test on your end, would you mind signing out of all accounts except your G Suite one and see if it still fails to export?

Sandstedt commented 5 years ago

I think we are on to something 🙂. I guess Google changed something recently.

I tried to log out of all other accounts. Also tried a incognito one. But same Access denied: Driveapp error in Firefox.

matt-wadsworth commented 4 years ago

Came across this same error today, using both sheets on a G Suite organisation or a personal account.

I've created new sheets to test, with the same errors. Had no problems for months prior to today.

Jo {message: "There was an error during the transport or process…this request. Error code = 10, Path = /wardeninit", name: "TransportError", stack: "TransportError: There was an error during the tran…4839744-warden_bin_i18n_warden__en_gb.js:189:247)"}
Uncaught  at exportDocument (ExportSheetData:1811) (Export Sheet Data:59) 9424292d-7319-4278-867f-12dda0a70ec3
 at exportSpreadsheetJson (ExportSheetData:1764) (Export Sheet Data:59) 9424292d-7319-4278-867f-12dda0a70ec3
 at exportJson (ExportSheetData:709) (Export Sheet Data:59) 9424292d-7319-4278-867f-12dda0a70ec3

Able to visualise the output JSON without problems, just not able to export to file.

Any ideas?

Synthoid commented 4 years ago

Someone else made an issue a few minutes before you commented here. I'll be posting my responses over there for the time being since issue was more about the G Suite update, but to summarize: I tested exporting both JSON and XML files from a G Suite account and it worked for me (both visualization and exporting). Would you be able to link an example sheet for me to test with? (Preferably in the other issue to avoid cluttering this one).