Google apps script 基于选定对象自动更新excel/google工作表中的下拉列表
我想实现以下场景,我有一个游戏,安装过程需要一个连接到2个数据库的队列,基于可用性 1。玩家Google apps script 基于选定对象自动更新excel/google工作表中的下拉列表,google-apps-script,google-sheets,dropdown,Google Apps Script,Google Sheets,Dropdown,我想实现以下场景,我有一个游戏,安装过程需要一个连接到2个数据库的队列,基于可用性 1。玩家 2。车辆 该列表包括一个“生成器”,这意味着每个单元格都有一个连接到数据库的下拉列表,并显示可用对象 我的目标 我需要在提交或从列表中选择一个对象时自动更新下拉列表,以便在单击下拉列表后,下一个单元格将不再包含该对象,而且如果我从列表中删除对象,该对象必须返回下拉列表,因为它再次可用 我做了什么? 我在数据库端做了一些公式,这样可以从一列创建下拉列表,一旦我从下拉列表本身为列表指定了一个对象,该列就会自
2。车辆 该列表包括一个“生成器”,这意味着每个单元格都有一个连接到数据库的下拉列表,并显示可用对象 我的目标 我需要在提交或从列表中选择一个对象时自动更新下拉列表,以便在单击下拉列表后,下一个单元格将不再包含该对象,而且如果我从列表中删除对象,该对象必须返回下拉列表,因为它再次可用 我做了什么? 我在数据库端做了一些公式,这样可以从一列创建下拉列表,一旦我从下拉列表本身为列表指定了一个对象,该列就会自动更新 第1列:包括所有可用车辆/玩家
第2列:包括所有分配的车辆/玩家
第3列:使用公式=
排序(过滤器(E2:E,F2:F=“”),1,true),从第2列减去第1列,生成下拉列表
问题
虽然这种方法“有效”,但我对下拉菜单自动更新的方式有一些问题
如果我添加所有可用设备,然后删除和项,以便它可以用于其他单元格/插槽,下拉列表将不会自动正确更新,如果我删除“unit 4”,下拉列表将显示另一个可用对象“unit 8”
我能做些什么来解决我的问题?
我正在为电子表格添加链接,以便更容易理解我的问题
谢谢你们
因此可以优化并清除此解决方案,添加一些函数以避免重复代码。但作为一个工作的起点,你可以
function onEdit(e) {
var ss = SpreadsheetApp.getActive();
// Get the working Sheets
var gameplan = ss.getSheetByName("gameplan");
var vehicle = ss.getSheetByName("vehicle");
var players = ss.getSheetByName("players");
// Get current selected vehicles
var _selectedVehicles = gameplan.getRange(2, 2, gameplan.getLastRow() - 1).getValues();
var selectedVehicles = [];
for(var i = 0; i < _selectedVehicles.length; i++){
selectedVehicles.push(_selectedVehicles[i][0])
}
// Get current selected players
var _selectedPlayers = gameplan.getRange(2, 1, gameplan.getLastRow() - 1).getValues();
var selectedPlayers = [];
for(var i = 0; i < _selectedPlayers.length; i++){
selectedPlayers.push(_selectedPlayers[i][0])
}
// Get active and unselected Vehicles
var activeVehicles = [];
var vehicleValues = vehicle.getRange(2, 1, vehicle.getLastRow() - 1, 2).getValues();
for(var i =0; i < vehicleValues.length; i++){
if(vehicleValues[i][0] == "ACTIVE" && selectedVehicles.indexOf(vehicleValues[i][1]) == -1){
activeVehicles.push(vehicleValues[i][1])
}
}
// Get active and unselected players
var activePlayers = [];
var playerValues = players.getRange(2, 1, players.getLastRow() - 1, 2).getValues();
for(var i =0; i < playerValues.length; i++){
if(playerValues[i][0] == "ACTIVE" && selectedPlayers.indexOf(playerValues[i][1]) == -1){
activePlayers.push(playerValues[i][1])
}
}
// Insert data validation for vehicles
var rule = SpreadsheetApp.newDataValidation().requireValueInList(activeVehicles, true).build();
gameplan.getRange("B2:B").setDataValidation(rule);
// Insert data validation for Players
var rule = SpreadsheetApp.newDataValidation().requireValueInList(activePlayers, true).build();
gameplan.getRange("A2:A").setDataValidation(rule);
}
这里基本上是调用电子表格上的
- 获取已选择的值
ACTIVE/INACTIVE
和id
。
之后,我们遍历数组,确保该行的状态为活动
,并且id不在先前选择的数组中。看这张照片。我们将所有符合这些条件的值存储在一个新数组中
- 最后,我们实施新的数据验证
对于最后一点,您需要使用的是创建对象的方法。在这个对象中,有很多方法可以让数据按照您想要的方式运行,其中一个方法是使用下拉列表显示您想要的值。在本例中,是我们在上一步中创建的数组。使用后,我们可以使用将此新规则添加到
范围
,这样可以优化并清除此解决方案,添加一些函数以避免重复代码。但作为一个工作的起点,你可以
function onEdit(e) {
var ss = SpreadsheetApp.getActive();
// Get the working Sheets
var gameplan = ss.getSheetByName("gameplan");
var vehicle = ss.getSheetByName("vehicle");
var players = ss.getSheetByName("players");
// Get current selected vehicles
var _selectedVehicles = gameplan.getRange(2, 2, gameplan.getLastRow() - 1).getValues();
var selectedVehicles = [];
for(var i = 0; i < _selectedVehicles.length; i++){
selectedVehicles.push(_selectedVehicles[i][0])
}
// Get current selected players
var _selectedPlayers = gameplan.getRange(2, 1, gameplan.getLastRow() - 1).getValues();
var selectedPlayers = [];
for(var i = 0; i < _selectedPlayers.length; i++){
selectedPlayers.push(_selectedPlayers[i][0])
}
// Get active and unselected Vehicles
var activeVehicles = [];
var vehicleValues = vehicle.getRange(2, 1, vehicle.getLastRow() - 1, 2).getValues();
for(var i =0; i < vehicleValues.length; i++){
if(vehicleValues[i][0] == "ACTIVE" && selectedVehicles.indexOf(vehicleValues[i][1]) == -1){
activeVehicles.push(vehicleValues[i][1])
}
}
// Get active and unselected players
var activePlayers = [];
var playerValues = players.getRange(2, 1, players.getLastRow() - 1, 2).getValues();
for(var i =0; i < playerValues.length; i++){
if(playerValues[i][0] == "ACTIVE" && selectedPlayers.indexOf(playerValues[i][1]) == -1){
activePlayers.push(playerValues[i][1])
}
}
// Insert data validation for vehicles
var rule = SpreadsheetApp.newDataValidation().requireValueInList(activeVehicles, true).build();
gameplan.getRange("B2:B").setDataValidation(rule);
// Insert data validation for Players
var rule = SpreadsheetApp.newDataValidation().requireValueInList(activePlayers, true).build();
gameplan.getRange("A2:A").setDataValidation(rule);
}
这里基本上是调用电子表格上的
- 获取已选择的值
ACTIVE/INACTIVE
和id
。
之后,我们遍历数组,确保该行的状态为活动
,并且id不在先前选择的数组中。看这张照片。我们将所有符合这些条件的值存储在一个新数组中
- 最后,我们实施新的数据验证
对于最后一点,您需要使用的是创建对象的方法。在这个对象中,有很多方法可以让数据按照您想要的方式运行,其中一个方法是使用下拉列表显示您想要的值。在本例中,是我们在上一步中创建的数组。使用后,我们可以使用将此新规则添加到
范围中。我有办法解决您的问题,但它要求每个选择都有一个“helper”列/行以及一个“checker”列
检查器将检查项目是否已使用,每个项目的帮助器列将基于剩余的可用选择
使用第1列和第2列,您只需要为每个选择添加一个辅助列
Below is an example:
A B B D E Column 1 (K) Column 2(L)
Chosen number 1 3 3 2 4 Random items
Chosen number 2 5 5 2 4 1 3
Chosen number 3 1 1 2 4 2 available
Chosen number 4 2 4 3 1
Chosen number 5 2 4 4 available
5 2
The formula in column C is '=B'
The formula in column D is '=transpose(filter($K$2:$K$6,$L$2:$L$6="available"))'
The data validation in column B is range C:F.
Column 1 includes all options
Column 2 includes all available options and the formula in column 2 is '=iferror(match(K2,$B$1:$B$5,0),"available")'
The purpose of column C is to allow for your data validation to be valid, even after entering in the selection.
我有办法解决您的问题,但它要求每个选择都有一个“helper”列/行以及一个“checker”列
检查器将检查项目是否已使用,每个项目的帮助器列将基于剩余的可用选择
使用第1列和第2列,您只需要为每个选择添加一个辅助列
Below is an example:
A B B D E Column 1 (K) Column 2(L)
Chosen number 1 3 3 2 4 Random items
Chosen number 2 5 5 2 4 1 3
Chosen number 3 1 1 2 4 2 available
Chosen number 4 2 4 3 1
Chosen number 5 2 4 4 available
5 2
The formula in column C is '=B'
The formula in column D is '=transpose(filter($K$2:$K$6,$L$2:$L$6="available"))'
The data validation in column B is range C:F.
Column 1 includes all options
Column 2 includes all available options and the formula in column 2 is '=iferror(match(K2,$B$1:$B$5,0),"available")'
The purpose of column C is to allow for your data validation to be valid, even after entering in the selection.
请选择一种方法,如果它们有一些相似之处,差异会使许多答案在不同平台上无法使用。请选择一种方法,如果它们有一些相似之处,差异会使许多答案在不同平台上无法使用。首先,我要说哇,感谢你在我的问题上所做的努力,我没有尝试脚本的原因之一是,多用户将对此工作表具有受保护的访问权限,因此执行此操作时脚本不是最好的。不过,如果你能给我一些建议,我将不胜感激。不管怎样,我会测试你的代码,然后会给你回复。所以在测试脚本后,一切正常,我能够按照要求自动更新。关于使用您的脚本,我还有一个问题,在从一个单元格中删除可用对象并显示在下拉列表中后,如何加快可用对象的速度?从下拉列表中删除已经添加的内容是一样的吗?它可以工作,但需要在其他地方单击2或4下才能刷新数据(下拉列表对象)。我在尝试添加另一个具有相同功能的列时疯了。但是,由于我不熟悉脚本,语法方面我失败了,您能告诉我如何使用o添加另一列吗
// Insert data validation for vehicles
var rule = SpreadsheetApp.newDataValidation().requireValueInList(activeVehicles, true).build();
gameplan.getRange("B2:B").setDataValidation(rule);
Below is an example:
A B B D E Column 1 (K) Column 2(L)
Chosen number 1 3 3 2 4 Random items
Chosen number 2 5 5 2 4 1 3
Chosen number 3 1 1 2 4 2 available
Chosen number 4 2 4 3 1
Chosen number 5 2 4 4 available
5 2
The formula in column C is '=B'
The formula in column D is '=transpose(filter($K$2:$K$6,$L$2:$L$6="available"))'
The data validation in column B is range C:F.
Column 1 includes all options
Column 2 includes all available options and the formula in column 2 is '=iferror(match(K2,$B$1:$B$5,0),"available")'
The purpose of column C is to allow for your data validation to be valid, even after entering in the selection.