0

I'm looking to transfer data from a number of Google Sheets to a website on Webflow. The data in the Sheets get updated over time (some automatically and some manually), and our website needs to dynamically update with it. We had this working up until a few weeks ago. We used Sheets’s “Publish to Web” functionality, then simply scraped from that page with an xmlhttp request.

Then, Google changed their system. The old links we used have been replaced with a page that says:

The Sheets v3 API has been turned down. Further information can be found at: https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api

With v4, You can still publish to web, but it outputs a different link and this one causes CORS issues when we try to request it with an xmlhttp call. We keep getting this error:

Access to XMLHttpRequest at 'https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pubhtml' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

I can’t figure out what to do with this, but in the process of researching I’ve found that it seems Google does not want people to be grabbing information from this publish page in the first place- it’s meant to be a link to send to people.

We’re not exactly sure what to do at this point and could use some help. Are there any work-arounds we’re unaware of, or is there a different system we could be using entirely?

The code:

let fonds_xmlhttp = new XMLHttpRequest();
        fonds_xmlhttp.onload = function () {
            if (this.readyState == 4 && this.status == 200){
                let fonds_data = JSON.parse(this.responseText);
                // do stuff with fonds_data
            } else {
                console.log("status: " + this.status);
            }
        };
fonds_xmlhttp.open("GET", 
                   "https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pubhtml", 
                   true);

EDIT:

This is the flow I'm now using... I'm just trying to open this html page in chrome, now using the script that @Tanaike provided:

<meta name="viewport" content="width=device-width, initial-scale=1">

<body> 
    <div>
        <table class="fonds-tabelle">
            <thead>
                <tr>
                    <th> </th>
                    <th>2021</th>
                    <th>2020</th>
                    <th>2019</th>
                    <th>2018</th>
                    <th>2017</th>
                    <th>2016</th>
                    <th>Ø 3J</th>
                    <th>Ø 5J</th>
                </tr>
            </thead>
            <tbody id="fonds-daten"> 
            </tbody>
        </table>   
    </div> 
</body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>
<script type="text/javascript">
    let fonds_xmlhttp = new XMLHttpRequest();
    fonds_xmlhttp.onload = function () {
      if (this.readyState == 4 && this.status == 200){
        let [header, ...values] = Papa.parse(this.responseText).data;
        values = values.map(r => r.map(c => {
          const t = c.trim();
          return isNaN(t) ? t : Number(t);
        }));
        const fonds_data = values.map(r => r.reduce((o, c, j) => Object.assign(o, {[header[j] && header[j].trim()]: c}), {}));
        console.log(fonds_data);

        /* Then iterate over fonds_data and fill the tbody fonds-daten with it */
      } else {
        console.log("status: " + this.status);
      }
    };
    const url = "https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pub?output=csv";
    fonds_xmlhttp.open("GET", url, true);
    fonds_xmlhttp.send();

</script>

I still get the following CORS error when I open this in Chrome:

Access to XMLHttpRequest at 'https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pub?output=csv' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

candybowl
  • 1
  • 2

1 Answers1

0

Issue and workaround:

I thought that the reason for your issue might be due to https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pubhtml.

In your situation, as a workaround, how about modifying your endpoint to https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pub?output=csv? By this, the data can be retrieved as CSV data. So, when the retrieved CSV data is parsed, you can convert it to a 2-dimensional array and JSON object.

The sample modified script is as follows.

Modified script:

In this modification, in order to parse the CSV data, the library of https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js is used.

let fonds_xmlhttp = new XMLHttpRequest();
fonds_xmlhttp.onload = function () {
  if (this.readyState == 4 && this.status == 200){
    let [header, ...values] = Papa.parse(this.responseText).data;
    values = values.map(r => r.map(c => {
      const t = c.trim();
      return isNaN(t) ? t : Number(t);
    }));
    const fonds_data = values.map(r => r.reduce((o, c, j) => Object.assign(o, {[header[j] && header[j].trim()]: c}), {}));
    console.log(fonds_data)
  } else {
    console.log("status: " + this.status);
  }
};
const url = "https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pub?output=csv";
fonds_xmlhttp.open("GET", url, true);
fonds_xmlhttp.send();
  • In this modified script, please add <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js"></script>. If you can parse the CSV data by your own script, you can achieve your goal without using this library.

  • When this modified script is run, the following result is obtained.

      [
        {"2016":"5,01%","2017":"6,20%","2018":"-5,06%","2019":"20,42%","2020":"3,98%","2021":"5,95%","":"Flossbach von Storch","D3J":"9,54%","D5J":"7,20%"},
        {"2016":"6,62%","2017":"6,81%","2018":"-3,42%","2019":"19,31%","2020":"13,32%","2021":"5,57%","":"Phaidros Balanced D","D3J":"10,88%","D5J":"9,82%"},
        {"2016":"-0,38%","2017":"10,09%","2018":"-11,14%","2019":"25,38%","2020":"13,99%","2021":"16,59%","":"ODDO BHF","D3J":"13,72%","D5J":"10,93%"},
        {"2016":"2,53%","2017":"8,88%","2018":"-0,42%","2019":"18,33%","2020":"7,08%","2021":"9,32%","":"Acatis Gané Value","D3J":"10,72%","D5J":"10,16%"},
        {"2016":"2,66%","2017":"12,81%","2018":"0,99%","2019":"27,33%","2020":"-1,40%","2021":"10,59%","":"Capital Growth","D3J":"12,18%","D5J":"11,80%"}
      ]
    
  • If you want to retrieve the data as the 2-dimensional array, you can retrieve it from Papa.parse(this.responseText).data.

Reference:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • Thank you for the detailed answer! Unfortunately, I'm still getting this CORS error... "Access to XMLHttpRequest at 'https://docs.google.com/spreadsheets/u/2/d/e/2PACX-1vTkGAWMFigGt-_40bYYtR9OuDh5t0gO0B5tAUhiUg2-XuSXfIazjgbvoqBxvQxxIPr62OfmdWQaWtPt/pub?output=csv' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource." – candybowl Oct 11 '21 at 17:28
  • @candybowl Thank you for replying. I apologize for this. Unfortunately, I cannot replicate your situation. When I tested my proposed script, no error occurs. I deeply apologize for this situation. So can you provide the detailed flow for correctly replicating your issue? By this, I would like to try to replicate it. – Tanaike Oct 11 '21 at 23:55
  • Ultimately, I'm going to run this all through WebFlow in html. But for now, I'm simply trying to get an html file working on Chrome. StackOverflow won't let me post the entire file in a comment, but I just copied your script into a – candybowl Oct 25 '21 at 17:25
  • @candybowl Thank you for replying. I have to apologize for my poor English skill again. Unfortunately, from your replying, I couldn't understand about the flow for correctly replicating your issue. So in order to correctly understand your current issue, can you provide the detailed flow for correctly replicating your issue? By this, I would like to try to replicate it. – Tanaike Oct 25 '21 at 23:56
  • thank YOU for all your help! I edited the original post to explain the flow. The comment section didn't allow enough characters. So please look at the post again, you'll see an "EDIT" section where I try your script in an html file. Thank you again! – candybowl Oct 26 '21 at 08:40
  • @candybowl Thank you for replying. I apologize for the inconvenience. Unfortunately, when I tested your script, no error occurs. I can confirm that the result values shown in my answer can be retrieved. This is due to my poor skill. I deeply apologize for this. In order to correctly understand your current situation, can you provide the detailed flow for replicating your issue? By the way, what browser are you using now? I tested this using Chrome. How about this? – Tanaike Oct 26 '21 at 11:51