【问题标题】:Auto updating drop down list in excel/google sheet based on selected objects根据所选对象自动更新 excel/google 工作表中的下拉列表
【发布时间】:2020-01-29 10:30:55
【问题描述】:

我想实现以下场景,我有一个游戏,设置过程需要一个连接到 2 个数据库的队列,根据可用性。

1.玩家
2.车辆

该阵容包括一个“builder”,这意味着每个单元格都有一个连接到数据库并显示可用对象的下拉列表。

我的目标

我需要在提交或从列表中选择一个对象后立即自动更新下拉列表,因此,一旦我单击下拉列表,下一个单元格将不再包含该对象,即使我从中删除了一个对象这个对象的阵容必须回到下拉列表,因为它再次可用。

我做了什么?

我在数据库端做了一些公式,因此可以从一个列创建下拉列表,一旦我从下拉列表本身将对象分配给列表,该列就会自动更新。

第 1 列:包括所有可用的载具/玩家
第 2 列:包括所有已分配的载具/玩家
第 3 列 :使用公式 =SORT(FILTER(E2:E,F2:F=""),1,true)

生成从 column2 中减去 column1 的下拉列表

问题

虽然这种方法“有效”,但下拉列表自动更新的方式存在一些问题 如果我添加所有可用设备,然后删除和项目,以便它可以用于另一个 cell/slot,如果我删除 "unit 4" 下拉列表将显示另一个可用的对象“unit 8”

我可以做些什么来解决我的问题?

我正在添加电子表格的链接,以便更容易理解我的问题。

谢谢你们。

googlespreadsheet

【问题讨论】:

  • 请选择一种方法,它们有一些相似之处,不同之处会使许多答案无法跨平台使用。

标签: google-apps-script google-sheets dropdown


【解决方案1】:

所以这个解决方案可以被优化和清理添加一些函数来不重复代码。但作为一个工作起点,你可以有。

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);



}

说明

从您的帖子中不清楚您之前是否使用过Apps Script。因此,为了确保您能够理解正在发生的事情(如果您想修改它),我将回顾我的代码,解释我使用的所有步骤和方法。

基本上,代码有 4 个部分。

  • 获取工作表
// Get the working Sheets
  var gameplan = ss.getSheetByName("gameplan");
  var vehicle = ss.getSheetByName("vehicle");
  var players = ss.getSheetByName("players");

这里基本上只是在电子表格上调用getSheetByName()

  • 获取已经选择的值
 // 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])
  } 

所以这里只是重复相同的代码两次。 在每张调用getRange 方法的工作表中。然后因为返回类型是Object[][],我们需要遍历并获取每个单独的值和push 它到selectedVehicles(或玩家)数组。

  • 获取激活和未选择的车辆
 // 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])
    }
  }

所以这里使用相同的getRange 方法来获取值,但在这种情况下,我们要检索两列,ACTIVE/INACTIVEid。 之后,我们遍历数组,确保该行具有ACTIVE 状态,并且 id 不在之前的 selected 数组中。看看indexOf。我们将与这些条件匹配的所有值存储在一个新数组中。

  • 最后我们实施了新的数据验证
// Insert data validation for vehicles
  var rule = SpreadsheetApp.newDataValidation().requireValueInList(activeVehicles, true).build();
  gameplan.getRange("B2:B").setDataValidation(rule);

对于最后一点,您需要使用创建DataValidationBuilder 对象的newDataValidation() 方法。在该对象中,您有很多方法可以使数据按照您的意愿运行,其中一种方法是 requireValueInList,可以使用您想要的值进行下拉。在我们在上一步中创建的数组的情况下。使用build 后,我们可以将此新规则添加到rangesedDataValidation

【讨论】:

  • 首先我要说哇,感谢您在我的问题上所做的努力,我没有尝试脚本的原因之一是因为多用户将保护访问此工作表,所以脚本不是最好的这个。但是,如果您能给我一些建议,将不胜感激。无论如何,我会测试你的代码会回复你。
  • 所以在测试脚本后一切正常,我能够按照要求自动更新。关于使用您的脚本,我还有一个问题,从一个单元格中删除可用对象然后出现在下拉列表中后,如何加快可用对象的速度?从下拉列表中删除已添加的相同内容?它可以工作,但需要在其他地方单击 2 或 4 次才能刷新该数据(下拉列表对象)
  • 我在尝试添加具有相同功能的另一列时大吃一惊。但是由于我不熟悉脚本,所以我在语法上失败了,你能告诉我如何在不破坏脚本引用等的情况下添加另一列吗? @Raserhin 谢谢。
  • 另一列是什么意思?您想要加速的究竟是什么?
【解决方案2】:

我有办法解决您的问题,但它需要每个选择的“帮助”列/行以及“检查器”列。

检查器将检查该项目是否被使用,每个项目的帮助列将基于剩余的可用选择。

使用您的第 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.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-13
    • 2022-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多