我一直在努力解决这个问题。我意识到这对于那些遵循GAS标签的人来说可能比平时更基本,但是任何帮助都非常值得赞赏。
如果我将更大的任务分解为组件部分,那么现在我的目标就是自动更新几个命名范围。
电子表格上有一个名为“DataImport”的标签。 DataImport有10列,全长1000行。每列有一个命名范围,例如卷心菜(A2:A1000),狗(B2:B1000)等
新菜单项“更新数据”附加了一个脚本,选中此项后会将csv文件导入DataImport选项卡,这意味着数据集的长度将会增加。
如何告诉工作表将每个命名范围更新为数据长度?因此,如果原始命名范围“cabbages”为A2:A1000并且更新后数据现在实际上与A2:A1500一样长,我如何告诉工作表更新范围卷心菜?
我在网上找到了一段代码并开始摆弄它:
function testNamedRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange('DataImport!A:A');
var data_len = range.length;
SpreadsheetApp.getUi().alert(data_len); // "alert just gives "undefined"
ss.setNamedRange('TestRange', range);
var rangeCheck = ss.getRangeByName('TestRange');
var rangeCheckName = rangeCheck.getA1Notation();
}
我的想法是,如果我可以使用自定义菜单功能获取更新后的数据长度,那么我可以使用setNamedRange()来更新cabbages范围。
我真的迷失了,我想这比我正在做的更简单。
如何将命名范围的cabbages更新为UpdateData列A中的数据长度?
答案 0 :(得分:1)
提供此函数我写了处理命名范围的动态调整大小:
function resizeNamedRange(rangeName, addRows, addCols) {
/* expands (or decreases) a range of a named range.
rows and columns to add can be negative (to decrease range of name). Params:
rangeName - name of range to resize.
addRows - number of rows to add (subtract) from current range.
addCols - number of columns to add (subtract) from current range.
Call example: resizeNamedRange("Products",1,0);
*/
var sh = SpreadsheetApp.getActiveSpreadsheet();
try {
var oldRange = sh.getRangeByName(rangeName);
var numRows = oldRange.getNumRows() + addRows;
var numCols = oldRange.getNumColumns() + addCols;
if (numRows < 1 || numCols <1) {
Logger.log("Can't resize a named range: minimum range size is 1x1.");
return;
}
sh.setNamedRange(rangeName, oldRange.offset(0,0,numRows, numCols));
} catch (e) {
Logger.log ("Failed resizing named range: %s. Make sure range name exists.", rangeName);
}
}
答案 1 :(得分:1)
也许我错过了一些东西,但下面的函数采用了一个范围名称和它应该包含的范围。如果rangename已存在,则将范围更新为传递的值。如果rangename不存在,则使用传递的范围值创建它。
关于“#REF!”表格中的问题。您可以执行查找和替换,并勾选“在公式中查找”框。把“#REF!”在查找和替换框中的命名范围名称。假设只删除了一个命名范围,并且没有其他无关的#REF!错误。这种方法帮助我修复了一个电子表格,误差分布在8个不同的表格和20多个公式上,仅需几分钟。
/**
* Corrects a named range to reflect the passed range or creates it if it doesn't exist.
*
* @param {string} String name of the Named Range
* @param {range} Range (not string, but range type from Sheet class)
* @return {void || range} returns void if Named Range had to be created, returns NamedRange class if just updated. This needs improvement.
* @customfunction
*/
function fixNamedRange (name, range) {
var i = 0;
var ss = SpreadsheetApp
.getActiveSpreadsheet();
var ssNamedRanges = ss.getNamedRanges();
for (i = 0; i<ssNamedRanges.length && ssNamedRanges[i].getName() != name; i++) {};
if (i == ssNamedRanges.length) {
return (ss.setNamedRange(name, range));
} else {
return (ssNamedRanges[i].setRange(range));
}
}
答案 2 :(得分:1)
我找到了解决方案!
我有一个带有下拉列表的单元格,其中包含公司在系统上注册的所有客户端,如果我们输入的名称未出现在列表中,则执行newClient函数。基本上,我们使用SpreadsheetApp.getUi()来保存新信息。引入客户数据后,函数将在客户工作表上创建新行,并在最后一行的提示中输入信息。完成后,自动更新下拉列表。
真正的函数在一个需要调用newClient的大函数内部,因此真正的函数将是newClient(client,clients),在该示例中,我放置了变量以使其变得更容易。
我希望它能起作用!
function newClient() {
var ss = SpreadsheetApp.getActive().getSheetByName('Clients'); // Sheet with all the client information, name, city, country...
var client = 'New company';
var clients = ss.getRange('A2:A').getValues();
var ui = SpreadsheetApp.getUi();
ui.alert('Client '+client+' does not exist, enter the next information.');
var city = ui.prompt('Enter city').getResponseText();
var country = ui.prompt('Enter country').getResponseText();
client = client.toUpperCase();
city = city.toUpperCase();
country = country.toUpperCase();
ui.alert('Here is the information you entered about '+client+':'+'\n\n'+'City: '+city+'\n\n'+'Country: '+country)
ss.insertRowAfter(ss.getLastRow()); // Insert a row after the last client
ss.getRange('A'+(clients.length+2)).setValue(client); // Let's suppose we have 150 clients, on the first row we have the titles Client, City, Country, then we have the 150 clients so the last client is on row 151, that's why we enter the new one on the 152
ss.getRange('B'+(clients.length+2)).setValue(city);
ss.getRange('C'+(clients.length+2)).setValue(country);
var namedRanges = SpreadsheetApp.getActive().getNamedRanges(); // We get all the named ranges in an array
for (var i = 0; i < namedRanges.length; i++) {
var name = namedRanges[0].getName();
if (name == 'Clients') { // All the clients are stored on 'Clients' named range
var range = ss.getRange('A2:A'); // Update the range of the 'Clients' named range
namedRanges[i].setRange(range);
}
}
ui.alert('Client created, you can find it on the drop down list.');
}