繁体   English   中英

仅使用JavaScript,如何查询Google工作表并将单个单元格的值分配为JavaScript变量?

[英]Using JavaScript only, how can I query a google sheet and assign the value of a single cell as a JavaScript variable?

我想使用一些Google表格中的数据来驱动网页。

我已经弄清楚了如何查询我的工作表,但是数据显示为数据表,而这并不是我想要的。 我希望能够获取查询单元格值并将其插入HTML代码。 我还将在另一个查询中使用该值,以便从其他Google工作表中检索其他信息。

我有两个实时页面: http : //www.bandstand.ca/widget

此页面是我的项目的入门版本。 我现在已经静态地对“第5天”进行了编码和格式化,但要按照以下查询数据替换它: http//www.bandstand.ca/widget/sas.html

我曾尝试使用getValue(0,0),但一定不能设置正确的东西。 我对使用查询完全陌生,还无法弄清JavaScript是否可以对响应的内容做任何事情。 我尝试隐藏查询填充的div元素并仅解析数据表的内容,但是同样,无法找到可行的解决方案。 我尝试搜索api文档,但找不到任何看起来正确的东西。 当然,有一种方法可以提取数据并在其他html中使用它。 我并不特别在乎代码是否干净(我敢肯定,您可以说,我已经破解了其他人的代码,以使sas.html文件降至其所在位置。)我只是想要一些可行的方法。

我是一名老师,并认为这是构建一个班级公告页面的简单小项目,该页面可以一直显示在我的房间中,并可以通过我轻松更新的Google表格在课程表中循环显示。 到目前为止,还不是那么容易! 如果有人可以帮助调整我的代码以获取我的要求,我将不胜感激!

您可以尝试如下操作:

 function GetCurrentDate() { var currentTime = new Date(); var month = currentTime.getMonth() + 2; var day = currentTime.getDate(); var year = currentTime.getFullYear(); var currentDate = "'" + year + "-" + month + "-" + day + "'"; return currentDate; } function CreateUrl(key, gql) { var gq = 'SELECT '+ gql; var encodedgg = encodeURIComponent(gq); var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg; return url; } function Request(url, responseFunction) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var response = this.responseText.substring(this.responseText.IndexOf("(")+1, this.responseText.lastIndexOf(")")); var responseJSON = JSON.parse(response); responseFunction(responseJSON); } }; xmlhttp.open("GET", url, true); xmlhttp.send(); } function preview(elm, url) { fetch(url) .then(data => data.text()) .then(function(response) { var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")")); var response = JSON.parse(responseText); var value = response['table']['rows'][0]['c'][0]['v']; elm.innerHTML = value; }) } var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ'; var currentDate = GetCurrentDate(); var gql = "C WHERE A = DATE " + currentDate; var url = CreateUrl(gsKey, gql); var previewElement = document.getElementById('preview'); preview(previewElement, url); 
 <html> <head> <title>Student Announcement System</title> </head> <body> <div id="preview">initial value</div> </body> </html> 

这是jsbin片段的链接。 (由于CORSAccess-Control-Allow-Origin,内联stackoverflow片段可能无法正常工作。)

格雷格·杜吉德(Greg Duguid)评论编辑

您的代码存在三个问题:

  1. 您的脚本根本不起作用。 尝试运行以下代码段:

 <script> document.write("Text 1") </script> <script language = "text/javascript"> document.write("Text 2") </script> <script type = "text/javascript"> document.write("Text 3") </script> 

当您运行它时,您应该得到类似于Text 1 Text 3 ,这是因为<script language = "text/javascript">是错误的并且不起作用,不推荐使用language参数,而应该使用type 同样在HTML5中,您可以省略type参数,因此最好使用类似<script>document.write("Text")</script>这样的语法。

  1. 函数preview有语法错误:最后一个括号(应为)

 // OLD CODE /* function preview(elm, url) { fetch(url) .then(data => data.text()) .then(function(response) { var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")")); var response = JSON.parse(responseText); var value = response['table']['rows'][0]['c'][0]['v']; //elm.innerHTML = value; DayNumber = value; } ( // ERROR IS IN THIS LINE } */ // NEW CODE function preview(elm, url) { fetch(url) .then(data => data.text()) .then(function(response) { var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")")); var response = JSON.parse(responseText); var value = response['table']['rows'][0]['c'][0]['v']; //elm.innerHTML = value; DayNumber = value; } ) // error WAS in this line } 

  1. 代码如下:

      <font size="+6" color="#FFFF00">Day <script>document.write(DayNumber);</script></font> 

    当您调用函数document.write(DayNumber)变量DayNumber等于""因为此时函数preview仍未执行。 原因是执行功能preview需要时间。 (因为通常是从工作表或类似的文件中检索数据,这是从工作表文档中检索数据的时间。)javascript中的代码执行是异步的,这意味着javscript不会等待函数完成执行并继续执行。 看这个例子:

     function getData() { // some function that takes time to get data from server, ducument, or something else return data; } var data = getData(); document.write(data); 

    在第一行中,调用了getData()函数,但是由于程序不会等待函数getData()返回其值,因此数据将被设置为undefined 因此,函数document.write(data)将不会预览任何内容。

    (在另一个标签内使用脚本标签也是一种不好的做法。因此,应避免将脚本标签放在字体标签内,如下所示: <font size="+6" color="#FFFF00">Day <script>document.write(DayNumber);</script></font> 。)

    解决此问题的方法是,将id添加到font标签中,然后在功能preview中的javascript中更改font标签中的文本:

 function GetCurrentDate() { var currentTime = new Date(); var month = currentTime.getMonth(); var day = currentTime.getDate() + 1; var year = currentTime.getFullYear(); var currentDate = "'" + year + "-" + month + "-" + day + "'"; return currentDate; } function CreateUrl(key, gql) { var gq = 'SELECT '+ gql; var encodedgg = encodeURIComponent(gq); var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg; return url; } function Request(url, responseFunction) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var response = this.responseText.substring(this.responseText.IndexOf("(")+1, this.responseText.lastIndexOf(")")); var responseJSON = JSON.parse(response); responseFunction(responseJSON); } }; xmlhttp.open("GET", url, true); xmlhttp.send(); } function preview(elm, url) { fetch(url) .then(data => data.text()) .then(function(response) { var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")")); var response = JSON.parse(responseText); var value = response['table']['rows'][0]['c'][0]['v']; elm.innerHTML += " " + value; } ) } var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ'; var currentDate = GetCurrentDate(); var gql = "C WHERE A = DATE " + currentDate; var url = CreateUrl(gsKey, gql); var previewElement = document.getElementById('preview'); preview(previewElement, url); 
 <html> <title>Student Announcement System</title> <body> <font size="+6" color="#FFFF00" id="preview">Day</font> </body> </html> 

最后的代码应该可以解决您的问题。 另外,这里是jsbin片段的链接 (因为当您运行它时stackoverflow片段可能不起作用)。

第二个Greg Duguid评论编辑

抱歉,花了一点时间才回答。 问题所在:

var previewElement = document.getElementById('preview');

执行此行时,未找到previewElement并且将其设置为undefined 这是因为脚本标记( <script>...</script> )中的javascript代码在body标记( <body>...</body> )之前,因此代码是在body的元素定义之前执行的。 因此,当您的页面运行时,首先执行javascript代码,然后定义元素<font id="preview">Day</font> 有一个简单的解决方案:您需要将script标签放在正文的末尾,如下所示:

 <html> <head> <style type="text/css"> <!-- body { background-color: #003c66; } --> </style> <title>Student Announcement System</title> </head> <body> <font size="+6" color="#FFFF00" id="preview">Day</font> <script> function GetCurrentDate() { var currentTime = new Date(); var month = currentTime.getMonth()+1; var day = currentTime.getDate(); var year = currentTime.getFullYear(); var currentDate = "'" + year + "-" + month + "-" + day + "'"; return currentDate; } function CreateUrl(key, gql, sheet) { var gq = 'SELECT '+ gql; var encodedgg = encodeURIComponent(gq); var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg + '&gid=' + sheet; return url; } function Request(url, responseFunction) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var response = this.responseText.substring(this.responseText.IndexOf("(")+1, this.responseText.lastIndexOf(")")); var responseJSON = JSON.parse(response); responseFunction(responseJSON); } }; xmlhttp.open("GET", url, true); xmlhttp.send(); } function preview(elm, url) { fetch(url) .then(data => data.text()) .then(function(response) { var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")")); var response = JSON.parse(responseText); var value = response['table']['rows'][0]['c'][0]['v']; elm.innerHTML += " " + value; } ) } var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ'; var gsSheet='349215948'; var currentDate = GetCurrentDate(); var gql = "C WHERE A = DATE " + currentDate; var url = CreateUrl(gsKey, gql, gsSheet); var previewElement = document.getElementById('preview'); preview(previewElement, url); </script> </body> </html> 

再次是应该工作的jsbin片段

Greg Duguid的评论之后进行编辑

问题出在您的查询中:

var PERIODgql = "C WHERE A = " + value + " AND B = " + CurrentPeriod;

CurrentPeriod是字符串,因此您需要像这样在其周围添加单引号:

var PERIODgql = "C WHERE A = " + value + " AND B = '" + CurrentPeriod + "'";

创建后, PERIODgql将类似于:

"C WHERE A = 1 AND B = 'P5'"

这些查询类似于SQL查询(用于从SQL数据库获取数据),您可以在此处阅读有关此内容的更多信息。

我也注意到你的功能FindCurrentPeriod

function FindCurrentPeriod() {
    var CurrentPeriod;
    var CurrentDate = new Date();

    //////////////////////////////
    //FOR TESTING VARIOUS TIMES
    CurrentDate.setHours(14);
    CurrentDate.setMinutes(0);
    //////////////////////////////


    var CurrentHour = CurrentDate.getHours();
    var CurrentMinute = CurrentDate.getMinutes();
    if (CurrentHour < 8) {
        CurrentPeriod = "Before School";
    }

    if (CurrentHour == 8) {
        if (CurrentMinute < 40) {
            CurrentPeriod = "Before School";
        } else {
            CurrentPeriod = "P1";
        }
    }

    if (CurrentHour == 9) {
        if (CurrentMinute < 40) {
            CurrentPeriod = "P1";
        } else {
            if (CurrentMinute < 45) {
                CurrentPeriod = "B12";
            } else {
                CurrentPeriod = "P2";
            }
        }
    }
    if (CurrentHour == 10) {
        if (CurrentMinute < 37) {
            CurrentPeriod = "P2";
        } else {
            if (CurrentMinute < 47) {
                CurrentPeriod = "B23";
            } else {
                CurrentPeriod = "P3";
            }
        }
    }

    if (CurrentHour == 11) {
        if (CurrentMinute < 39) {
            CurrentPeriod = "P3";
        } else {
            if (CurrentMinute < 44) {
                CurrentPeriod = "B34";
            } else {
                CurrentPeriod = "P4";
            }
        }
    }
    if (CurrentHour == 12) {
        if (CurrentMinute < 36) {
            CurrentPeriod = "P4";
        } else {
            CurrentPeriod = "Lunch";
        }
    }

    if (CurrentHour == 13) {
        if (CurrentMinute < 13) {
            CurrentPeriod = "Lunch";
        } else {
            CurrentPeriod = "P5";
        }
    }

    if (CurrentHour == 14) {
        if (CurrentMinute < 5) {
            CurrentPeriod = "P5";
        } else {
            if (CurrentMinute < 10) {
                CurrentPeriod = "B56";
            } else {
                CurrentPeriod = "P6";
            }
        }
    }

    if (CurrentHour == 15) {
        if (CurrentMinute < 2) {
            CurrentPeriod = "P6";
        } else {
            CurrentPeriod = "After School";
        }
    } else {
        CurrentPeriod = "After School";
    }
    return CurrentPeriod;

}

在这种情况下,它并不是很容易阅读,并且存在一些重复的条件,因此,如果以后需要更改代码,将很难做到。 因此,我建议您使用一个函数来帮助您比较时间(以小时和分钟为单位)。 您可以像这样添加短函数:

function time(hours, minutes) {
    return hours*60 + minutes;
}

现在,您可以像这样比较时间10:50和11:25:

if (time(10,50) < time(11,25)) {
    //part when you do what you want if condition is ture
}

因此,您可以这样编写函数FindCurrentPeriod

function FindCurrentPeriod() {
    var CurrentPeriod;
    var CurrentDate = new Date();

    //////////////////////////////
    //FOR TESTING VARIOUS TIMES
    CurrentDate.setHours(14);
    CurrentDate.setMinutes(0);
    //////////////////////////////

    var CurrentHour = CurrentDate.getHours();
    var CurrentMinute = CurrentDate.getMinutes();
    var cirrentTime = time(CurrentHour, CurrentMinute);

    if (cirrentTime < time(8, 40)) {
        CurrentPeriod = "Before School";
    }
    else if (cirrentTime < time(9, 40)) {
        CurrentPeriod = "P1";
    }
    else if (cirrentTime < time(9, 45)) {
        CurrentPeriod = "B12";
    }
    else if (cirrentTime < time(10, 37)) {
        CurrentPeriod = "P2";
    }
    else if (cirrentTime < time(10, 47)) {
        CurrentPeriod = "B23";
    }
    else if (cirrentTime < time(11, 39)) {
        CurrentPeriod = "P3";
    }
    else if (cirrentTime < time(11, 44)) {
        CurrentPeriod = "P3";
    }
    else if (cirrentTime < time(12, 36)) {
        CurrentPeriod = "P4";
    }
    else if (cirrentTime < time(13, 13)) {
        CurrentPeriod = "Lunch";
    }
    else if (cirrentTime < time(14, 5)) {
        CurrentPeriod = "P5";
    }
    else if (cirrentTime < time(14, 10)) {
        CurrentPeriod = "B56";
    }
    else if (cirrentTime < time(15, 2)) {
        CurrentPeriod = "P6";
    }
    else {
        CurrentPeriod = "After School";
    }


    return CurrentPeriod;

}

它更短,并且在需要时更易于阅读和更改。

这是stackoverflow片段中的完整代码(再次,我将在下面添加jsbin片段,因为由于CORS规则,内联stackoverflow片段可能不起作用):

 function preview2(elm, url) { fetch(url) .then(data => data.text()) .then(function(response) { var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")")); var response = JSON.parse(responseText); var value = response['table']['rows'][0]['c'][0]['v']; elm.innerHTML = value; }) } function GetCurrentDate() { var currentTime = new Date(); var month = currentTime.getMonth() + 1; var day = currentTime.getDate(); var year = currentTime.getFullYear(); var currentDate = "'" + year + "-" + month + "-" + day + "'"; return currentDate; } function CreateUrl(key, gql, sheet) { var gq = 'SELECT ' + gql; var encodedgg = encodeURIComponent(gq); var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg + '&gid=' + sheet; return url; } function time(hours, minutes) { return hours*60 + minutes; } function FindCurrentPeriod() { var CurrentPeriod; var CurrentDate = new Date(); ////////////////////////////// //FOR TESTING VARIOUS TIMES CurrentDate.setHours(14); CurrentDate.setMinutes(0); ////////////////////////////// var CurrentHour = CurrentDate.getHours(); var CurrentMinute = CurrentDate.getMinutes(); var cirrentTime = time(CurrentHour, CurrentMinute); if (cirrentTime < time(8, 40)) { CurrentPeriod = "Before School"; } else if (cirrentTime < time(9, 40)) { CurrentPeriod = "P1"; } else if (cirrentTime < time(9, 45)) { CurrentPeriod = "B12"; } else if (cirrentTime < time(10, 37)) { CurrentPeriod = "P2"; } else if (cirrentTime < time(10, 47)) { CurrentPeriod = "B23"; } else if (cirrentTime < time(11, 39)) { CurrentPeriod = "P3"; } else if (cirrentTime < time(11, 44)) { CurrentPeriod = "P3"; } else if (cirrentTime < time(12, 36)) { CurrentPeriod = "P4"; } else if (cirrentTime < time(13, 13)) { CurrentPeriod = "Lunch"; } else if (cirrentTime < time(14, 5)) { CurrentPeriod = "P5"; } else if (cirrentTime < time(14, 10)) { CurrentPeriod = "B56"; } else if (cirrentTime < time(15, 2)) { CurrentPeriod = "P6"; } else { CurrentPeriod = "After School"; } return CurrentPeriod; } function preview1(elm, url) { fetch(url) .then(data => data.text()) .then(function(response) { var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")")); var response = JSON.parse(responseText); var value = response['table']['rows'][0]['c'][0]['v']; elm.innerHTML += " " + value; var CurrentPeriod = FindCurrentPeriod(); var PERIODgsSheet = '618896702'; var PERIODgql = "C WHERE A = " + value + " AND B = '" + CurrentPeriod + "'"; var PeriodURL = CreateUrl(gsKey, PERIODgql, PERIODgsSheet); var periodElement = document.getElementById('period1'); preview2(periodElement, PeriodURL); }) } var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ'; var DAYgsSheet = '349215948'; var currentDate = GetCurrentDate(); var DAYgql = "C WHERE A = DATE " + currentDate; var DayURL = CreateUrl(gsKey, DAYgql, DAYgsSheet); var previewElement = document.getElementById('preview'); preview1(previewElement, DayURL); 
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="refresh" content="600" /> <title>Student Announcement System</title> <style type="text/css"> <!-- body { background-color: #003c66; } --> </style> <!-- CSS Code --> <style type="text/css" scoped> .GeneratedMarquee { font-family:'Arial Black', sans-serif; font-size:8em; font-weight:bold; line-height:2em; text-align:left; color:#ffff00; background-color:#003c66; padding:40pt; } </style> </head> <body> <table width=100%> <tr> <td width=240px> <iframe scrolling="no" frameborder="no" clocktype="html5" style="overflow:hidden;border:0;margin:0;padding:0;width:240px;height:80px;"src="https://www.clocklink.com/html5embed.php?clock=004&timezone=MST&color=white&size=240&Title=&Message=&Target=&From=2018,1,1,0,0,0&Color=white"></iframe> </td> <td nowrap> <center> <font size="80px" color="#FFFF00" id="preview">DAY </font> </center> </td> <td width=100%> <a class="weatherwidget-io" href="https://forecast7.com/en/53d54n113d49/edmonton/" data-label_1="EDMONTON" data-font="Helvetica" data-icons="Climacons Animated" data-days="7" data-theme="original" data-basecolor="#003c66" ></a> <script> !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src='https://weatherwidget.io/js/widget.min.js';fjs.parentNode.insertBefore(js,fjs);}}(document,'script','weatherwidget-io-js'); </script> </td> </tr> </table> <font color="FFFFFF", size="+6"> <script language=javascript> var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; var today = new Date(); document.write(today.toLocaleDateString("en-US", options)); // Saturday, September 17, 2016 formattedDate = today.toLocaleDateString("en-US", options); </script> </font> <br><font size="80px" color="#FFFF00" id="period1">Class:</font> <script src="sas.js"></script> </body> </html> 

这是jsbin片段

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM