Как сделать так, чтобы на боковой панели отображались значения из ячеек?
У меня есть Google Sheet, который я использую в качестве базы данных клиентов. Существует довольно много переменных (столбцов), которые мне нужно хранить для каждой записи, поэтому я подумал, что было бы проще просмотреть каждую запись, если бы на боковой панели отображались все значения активной строки.
Пример. Если щелкнуть ячейку C1, на боковой панели отобразятся значения C1, C2, C3 и C4.
Это возможно? Я дошел до отображения боковой панели, но не могу понять, как получить значение из ячейки и распечатать его на боковой панели.
Заранее спасибо, я зашел в тупик с моим (очень) ограниченным интеллектом!
1 ответ
Что-то вроде этого?
В этом дополнении используется идея опроса из опроса Google Doc из надстройки для вызова функции сервера. getRecord()
, Эта функция захватывает строку данных, которая выбрана в данный момент, и возвращает ее showRecord()
обратный вызов на стороне клиента (JavaScript), который обрабатывает представление на боковой панели.
Это не завершено - следите за комментариями TODO. Интересно, стоило ли бы это дальше развивать и публиковать?
Code.gs
/**
* @OnlyCurrentDoc Limits the script to only accessing the current spreadsheet.
*/
var SIDEBAR_TITLE = 'Record Viewer';
/**
* Adds a custom menu with items to show the sidebar and dialog.
*
* @param {Object} e The event parameter for a simple onOpen trigger.
*/
function onOpen(e) {
SpreadsheetApp.getUi()
.createAddonMenu()
.addItem('View records', 'showSidebar')
.addToUi();
}
/**
* Runs when the add-on is installed; calls onOpen() to ensure menu creation and
* any other initializion work is done immediately.
*
* @param {Object} e The event parameter for a simple onInstall trigger.
*/
function onInstall(e) {
onOpen(e);
}
/**
* Opens a sidebar. The sidebar structure is described in the Sidebar.html
* project file.
*/
function showSidebar() {
var ui = HtmlService.createTemplateFromFile('Sidebar')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle(SIDEBAR_TITLE);
SpreadsheetApp.getUi().showSidebar(ui);
}
/**
* Returns the active row.
*
* @return {Object[]} The headers & values of all cells in row.
*/
function getRecord() {
// Retrieve and return the information requested by the sidebar.
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var headers = data[0];
var rowNum = sheet.getActiveCell().getRow();
if (rowNum > data.length) return [];
var record = [];
for (var col=0;col<headers.length;col++) {
var cellval = data[rowNum-1][col];
// Dates must be passed as strings - use a fixed format for now
if (typeof cellval == "object") {
cellval = Utilities.formatDate(cellval, Session.getScriptTimeZone() , "M/d/yyyy");
}
// TODO: Format all cell values using SheetConverter library
record.push({ heading: headers[col],cellval:cellval });
}
return record;
}
Sidebar.html
<!-- Use a templated HTML printing scriptlet to import common stylesheet. -->
<?!= HtmlService.createHtmlOutputFromFile('Stylesheet').getContent(); ?>
<!-- Below is the HTML code that defines the sidebar element structure. -->
<div class="sidebar branding-below">
<p>
This sidebar displays all cells in a row, as a "record".
</p>
<!-- The div-table class is used to make a group of divs behave like a table. -->
<div class="block div-table" id="sidebar-record-block">
</div>
<div class="block" id="sidebar-button-bar">
</div>
<div id="sidebar-status"></div>
</div>
<!-- Enter sidebar bottom-branding below. -->
<div class="sidebar bottom">
<img alt="Add-on logo" class="logo" width="25"
src="https://googledrive.com/host/0B0G1UdyJGrY6XzdjQWF4a1JYY1k/apps-script_2x.png">
<span class="gray branding-text">Record Viewer by Mogsdad</span>
</div>
<!-- Use a templated HTML printing scriptlet to import JavaScript. -->
<?!= HtmlService.createHtmlOutputFromFile('SidebarJavaScript').getContent(); ?>
SidebarJavascript.html
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
/**
* Run initializations on sidebar load.
*/
$(function() {
// Assign handler functions to sidebar elements here, if needed.
// Call the server here to retrieve any information needed to build
// the dialog, if necessary.
// Start polling for updates
poll();
});
/**
* Poll a server-side function at the given interval, to have
* results passed to a successHandler callback.
*
* https://stackru.com/a/24773178/1677912
*
* @param {Number} interval (optional) Time in ms between polls.
* Default is 2s (2000ms)
*/
function poll(interval) {
interval = interval || 1000;
setTimeout(function() {
google.script.run
.withSuccessHandler(showRecord)
.withFailureHandler(
function(msg, element) {
showStatus(msg, $('#button-bar'));
element.disabled = false;
})
.getRecord();
}, interval);
};
/**
* Callback function to display a "record", or row of the spreadsheet.
*
* @param {object[]} Array of field headings & cell values
*/
function showRecord(record) {
if (record.length) {
for (var i = 0; i < record.length; i++) {
// build field name on the fly, formatted field-1234
var str = '' + i;
var fieldId = 'field-' + ('0000' + str).substring(str.length)
// If this field # doesn't already exist on the page, create it
if (!$('#'+fieldId).length) {
var newField = $($.parseHTML('<div id="'+fieldId+'"></div>'));
$('#sidebar-record-block').append(newField);
}
// Replace content of the field div with new record
$('#'+fieldId).replaceWith('<div id="'+fieldId+'" class="div-table-row"></div>');
$('#'+fieldId).append($('<div class="div-table-th">' + record[i].heading + '</div>'))
.append('<div class="div-table-td">' + record[i].cellval + '</div>');
}
}
// TODO: hide any existing fields that are beyond the current record length
//Setup the next poll
poll();
}
/**
* Displays the given status message in the sidebar.
*
* @param {String} msg The status message to display.
* @param {String} classId The message type (class id) that the message
* should be displayed as.
*/
function showStatus(msg, classId) {
$('#sidebar-status').removeClass().html(msg);
if (classId) {
$('#sidebar-status').addClass(classId);
}
}
</script>
Stylesheet.html
<!-- This CSS package applies Google styling; it should always be included. -->
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<style>
label {
font-weight: bold;
}
.branding-below {
bottom: 54px;
top: 0;
}
.branding-text {
left: 7px;
position: relative;
top: 3px;
}
.logo {
vertical-align: middle;
}
.width-100 {
width: 100%;
box-sizing: border-box;
-webkit-box-sizing : border-box;
-moz-box-sizing : border-box;
}
#sidebar-value-block,
#dialog-elements {
background-color: #eee;
border-color: #eee;
border-width: 5px;
border-style: solid;
}
#sidebar-button-bar,
#dialog-button-bar {
margin-bottom: 10px;
}
.div-table{
display:table;
width:auto;
/* background-color:#eee;
border:1px solid #666666;*/
border-spacing:5px;
}
.div-table-row{
display:table-row;
width:auto;
clear:both;
}
.div-table-td, .div-table-th {
display:table-cell;
width:200px;
background-color:rgb(230, 230, 230);
}
.div-table-th {
/*float:left;*/
font-weight: bold;
}
.div-table-td {
/*float:right;*/
}
</style>
Или, пять лет спустя, что-то вроде этого?
Это, скорее, развитие ответа Могсдада, но по-прежнему отвечает на OP.
Данные в TBA позиционируются по ассоциациям, а не по координатам - списки троп, ветвей и аспектов читаются отдельно и объединяются - Этаж 1 > Комната для гостей 3 > Тест 1: Грязный. (см. обзор TBA)
<<< Отображает данные для одного аспекта в электронной таблице; >>> Повторное выполнение для новых выделений в листе TBA.
Хочу поделиться кодом. Могу я спросить, как лучше всего это сделать? (Это очень ранние дни)