Используя только JavaScript, как я могу запросить лист Google и назначить значение отдельной ячейки в качестве переменной JavaScript? - PullRequest
0 голосов
/ 03 ноября 2018

Я хочу управлять веб-страницей, используя данные из нескольких листов 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 листы. Пока не все так просто! Если кто-то может помочь настроить мой код, чтобы получить то, что я прошу, я был бы признателен!

1 Ответ

0 голосов
/ 04 ноября 2018

Вы можете попробовать что-то вроде этого:

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 . (Фрагмент встроенного стекового потока может не работать из-за CORS и Access-Control-Allow-Origin .)

РЕДАКТИРОВАТЬ после Комментарий Грега Дюгида :

Есть три проблемы с вашим кодом:

  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(), но для данных будет установлено значение undefined, поскольку программа не будет ждать, пока функция getData() вернет свое значение. Так что функция document.write(data) не будет ничего просматривать.

    (Также не рекомендуется использовать тег script внутри другого тега. Поэтому не следует помещать тег script внутри тега шрифта следующим образом: <font size="+6" color="#FFFF00">Day <script>document.write(DayNumber);</script></font>.)

    Решение этой проблемы состоит в том, что вы добавляете id к вам тег font и затем изменяете текст в теге font в javascript внутри функции preview:

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 может не работать при его запуске).

РЕДАКТИРОВАТЬ после второго комментария Грега Дюгида :

Извините, что ответ занял немного больше времени. Проблема в строке:

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

Когда эта строка выполняется, previewElement не найден и для нее установлено значение undefined. Это связано с тем, что код JavaScript в теге script (<script>...</script>) находится перед тегом 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 , который должен работать.

РЕДАКТИРОВАТЬ после этого комментария Грега Дугуида :

Проблема в вашем запросе:

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 ниже, потому что встроенный фрагмент stackoverflow может не работать из-за правил CORS):

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 .

...