我需要同步相互引用的2个电子表格的内容,如果在其中一个表格中添加了新行,则保持其行同步。
我在Google表格中有2个电子表格(尽管如果有一个交叉电子表格解决方案,Excel和GS都会很棒):
它的工作方式是party1在A1-F10行的数据中写入,然后party2根据party1写入的内容在spreadsheet2中写入其他数据。
例如,如果Spreadsheet1 A1:F10是商品的名称,价格,交货时间,数量等,Spreadsheet2 G1:M10可能是订单日期的一堆数据,已交付(是/否)等。< / p>
我目前面临的问题是,当设置电子表格时,他们会在电子表格2中读取精细数据,即电子表格1中的1-10行,电子表格中为1-10,但过了一段时间,一些新行被添加到电子表格1之间第2-5行。这会抛出电子表格2中的顺序(现在,电子表格1中的第4行与电子表格2中的第4行不对齐,并且数据变得格格不入)。是否存在此问题,即使有人在现有行的中间添加了其他行,两个电子表格都会更新?
答案 0 :(得分:5)
这是数据库设计中的经典问题;如何将信息关联到两个表中。通常的解决方案是使用关键数据;两个表中存在的一个或多个列,并提供关联行的唯一标识符或键。
我们可以根据您的情况调整这个想法,使用一个脚本来调整电子表格2中行的位置以与电子表格1同步。为此,我们需要识别一个键 - 比如名称列 - 必须存在在两个电子表格中。
这需要在电子表格2中进行少量更改,其中名称列现在将显示在G列中,跟随A-F列中的导入范围。
A B C D E F G H I J
| Name | Price | est delivery time | qty | etc. of | an item | Name | order date | delivered | blah blah |
< - - - - - - - - - - - - Imported - - - - - - - - - - - > *KEY* < - - - - - - sheet 2 - - - - - >
这就是行动的样子!此示例在同一电子表格中使用两个工作表,仅为方便起见。在演示中,在工作表1的中间添加了一个新的“项目”行,由于=IMPORTRANGE()
功能,它会自动显示在工作表2上。同步功能在1分钟的定时触发器上运行,您将看到它在大约20秒内移动。
您可以获取电子表格+嵌入式脚本here的副本。
/**
* Call syncTables() with the name of a key column.
*/
function doSyncTables() {
syncTables( "Name" );
}
/*
* Sync "Orders" spreadsheet with imported rows from "Items" spreadsheet.
*
* From: http://stackoverflow.com/a/33172975/1677912
*
* @param {String} keyName Column header used as key colum, appears
* at start of "Orders" data, following
* "Items" data.
*/
function syncTables( keyName ) {
var sheet2 = SpreadsheetApp.openById( sheetId2 ).getSheetByName('Orders');
// Get data
var lastCol = sheet2.getLastColumn();
var lastRow = sheet2.getLastRow(); // Includes all rows, even blank, because of =importRange()
var headers = sheet2.getRange(1, 1, 1, lastCol).getValues()[0];
var keyCol = headers.lastIndexOf( keyName ) + 1;
var itemKeys = sheet2.getSheetValues(1, 1, lastRow, 1).map(function(row) {return row[0]});
var itemData = sheet2.getSheetValues(1, 1, lastRow, keyCol-1);
var orderData = sheet2.getSheetValues(1, keyCol, lastRow, lastCol-keyCol+1);
var ordersByKey = []; // To keep track of orders by key
// Scan keys in orderData
for (var row=1; row<orderData.length; row++) {
// break loop if we've run out of data.
var orderKey = orderData[row][0];
if (orderKey === '') break;
ordersByKey[ orderKey ] = orderData.slice(row, row+1)[0];
var orderKey = orderData[row][0];
}
var newOrderData = []; // To store reordered rows
// Reconcile with Items, fill out array of matching orders
for (row = 1; row<itemData.length; row++) {
// break loop if we've run out of data.
var itemKey = itemData[row][0];
if (itemKey === '') break;
// With each item row, match existing order data, or add new
if (ordersByKey.hasOwnProperty(itemKey)) {
// There is a matching order row for this item
newOrderData.push(ordersByKey[itemKey]);
}
else {
// This is a new item, create a new order row with same key
var newRow = [itemKey];
// Pad out all columns for the new row
for (var col=1; col<orderData[0].length; col++) newRow.push('');
newOrderData.push(newRow);
}
}
// Update spreadsheet with reorganized order data
sheet2.getRange(2, keyCol, newOrderData.length, newOrderData[0].length).setValues(newOrderData);
}
答案 1 :(得分:1)
mogsdad目前的答案一如既往的伟大。我只是想指出一个不太复杂的选择:
如果你可以忍受阻止spreadsheet1允许插入或删除行,你将避免这个问题。而不是删除行,您可以使用列来标记“已删除”(并使用过滤器从视图中删除)。
要防止电子表格1中的行插入和删除,只需选择右侧的整个未使用的列,并创建一个受保护的范围,以便所有编辑者都没有权限。这会阻止在行级别修改到最后一个现有行(但仍可以在该范围下插入新行)
它也不会阻止用户交换两行的数据。但是对于这个更简单的替代方案仍然有用。