确定在自定义菜单中单击了哪个项目

时间:2018-06-27 07:50:45

标签: javascript google-apps-script google-sheets google-sheets-api google-apps-script-editor

我创建了一个包含多个项目的自定义菜单,但是我很难确定用户单击了哪个项目。我想对该菜单中的每个项目使用相同的功能,但是我不知道如何传递将哪个项目按下到我的函数中的信息。我已经实现但尚未实现的多个想法是:尝试在按下按钮时传递参数(该参数可以是按钮的名称或其索引),或者试图以某种方式确定单击了哪个项目按索引(即“单击了项目3”)并将该信息传递给函数。

var ui = SpreadsheetApp.getUi(); //shortcut to access ui methods
var ps = PropertiesService.getScriptProperties(); //shortcut to access properties methods
var ss = SpreadsheetApp.getActiveSpreadsheet() //shortcut to access spreadsheet methods

function onOpen() {
  var menu = ui.createMenu('Scripts') //create a menu with this name
  var subMenu = ui.createMenu('Timestamps')
        for (var n = 0; n < ss.getNumSheets(); n++){
          var sheets = ss.getSheets();
          var sheetName = sheets[n].getName();
          Logger.log(sheetName)
          subMenu.addItem(sheetName, 'sheets')
        }
      menu.addSubMenu(subMenu).addToUi(); //add it to the UI
}

function sheets(sheet){
  var response = ui.alert(sheet, 'Add to timestamps?', ui.ButtonSet.YES_NO_CANCEL) //create a button and store the user value in response
  if(response == ui.Button.YES){ //if the user pressed YES (add this item to timestamp list)
    if(sheets.indexOf(sheet) != -1){ //check if item is already in the array. If it is, do nothing
      //item is aleady in array
    }else if(sheets.indexOf(sheet) == -1){ //check if it is NOT in the array. If it isn't, add it
      //item isn't in array, but needs to be added
      sheets.push(sheet) //add the item to the array
    }
  }else if(response == ui.Button.NO){ //if the user pressed NO (remove item from the list)
    if(sheets.indexOf(sheet) != -1){ //if the item already exists but needs to be removed)
      //item exists in array, but needs to be removed
      var index = sheets.indexOf(sheet); //find where the item is stored
      sheets.splice(index, 1); //splice that item out of the array
    }else if(sheets.indexOf(sheet) == -1){ //if the item already doesn't exist in the array, do nothing
      //item already isn't in array
    }
  }
  ps.setProperty('updatedSheets', JSON.stringify(sheets)) //storing the new value of sheets so that we can view it in the properties screen (only for debugging purposes)
}

此代码当前执行的操作是在打开电子表格时,创建一个名为Scripts的菜单,其中包含一个名为Timestamps的子菜单。在子菜单时间戳中,每张纸都有一个项目。目的是当用户单击其中一项时,将显示一个带有3个按钮的弹出窗口:“是”,“否”和“取消”。如果他们按是,则应将该项目添加到阵列表中。如果他们按No,则应该删除该项目。如果他们按取消,则什么也不会发生。到目前为止,如果它们在代码中指定了一个特定的工作表,则可以添加和删除这些项目,但是如何获取它,以便可以对每个项目使用相同的功能并传递参数工作表(取决于哪个项目是点击)进入功能表。

如果我在不将参数传递给函数的情况下对工作表名称进行硬编码,则该代码的功能示例:

function sheets(){
  var response = ui.alert('Sheet1', 'Add to timestamps?', ui.ButtonSet.YES_NO_CANCEL) //create a button and store the user value in response
  if(response == ui.Button.YES){ //if the user pressed YES (add this item to timestamp list)
    if(sheets.indexOf('Sheet1') != -1){ //check if item is already in the array. If it is, do nothing
      //item is aleady in array
    }else if(sheets.indexOf('Sheet1') == -1){ //check if it is NOT in the array. If it isn't, add it
      //item isn't in array, but needs to be added
      sheets.push('Sheet1') //add the item to the array
    }
  }else if(response == ui.Button.NO){ //if the user pressed NO (remove item from the list)
    if(sheets.indexOf('Sheet1') != -1){ //if the item already exists but needs to be removed)
      //item exists in array, but needs to be removed
      var index = sheets.indexOf('Sheet1'); //find where the item is stored
      sheets.splice(index, 1); //splice that item out of the array
    }else if(sheets.indexOf('Sheet1') == -1){ //if the item already doesn't exist in the array, do nothing
      //item already isn't in array
    }
  }
  ps.setProperty('updatedSheets', JSON.stringify(sheets)) //storing the new value of sheets so that we can view it in the properties screen (only for debugging purposes)
}

2 个答案:

答案 0 :(得分:0)

我知道eval是邪恶的,但我不禁使用它。是的,如果您通过eval动态创建了一堆函数,那么其余的就微不足道了。

var FUNC_STR = 'sheets';  //the real function name (global constant)

function onOpen() {
  //...
  for(var n = 0; n < ss.getNumSheets(); n++){
    var sheets = ss.getSheets();
    var sheetName = sheets[n].getName();
    subMenu.addItem(sheetName, FUNC_STR + n);  //note here
  }
  menu.addSubMenu(subMenu).addToUi();
}


//dynamically make functions
var evalString = '';
for(var n = 0; n < ss.getNumSheets(); n++) {
  evalString += 'function ' + FUNC_STR + n + '() { ' + 
    FUNC_STR + '(' + n + ') }';
}
eval(evalString);


//now you can take a argument.
//function name should be the same as FUNC_STR.
function sheets(sheet) {
  SpreadsheetApp.getUi().alert(sheet);
  //...
}

答案 1 :(得分:0)

这并不是您所提问题的真正答案,但我认为您将自己弄得太复杂了,这个答案可能会对其他人有所帮助...对于正在进行的项目,我需要同样的东西,并且我想到了一个好主意。在HTML中,我制作了菜单各部分的表格:

            <ul class='custom-menu' id="main-menu">
              <li data-action="One">Custom menu click one</li>
              <li data-action="Two">Custom menu click two</li>
              <li data-action="Three">Custom menu click three</li>
            </ul>
            <ul class='custom-menu' id="subMenuOne">
              <li data-action="sub1">Sub Menu One</li>
              <li data-action="sub2">Sub Menu Two</li>
              <li data-action="sub3">Sub Menu Three</li>
            </ul>

然后,我在表格中添加了样式,并在用鼠标悬停一行时,更改了颜色,并在鼠标更改的图标上进行了更改。您不需要这种样式。有创意:

        .custom-menu {
            display: none;
            z-index: 1000;
            position: absolute;
            overflow: hidden;
            border: 1px solid #CCC;
            white-space: nowrap;
            font-family: sans-serif;
            background: #FFF;
            color: #333;
            border-radius: 5px;
            padding: 0;
        }

        .custom-menu li {
            padding: 8px 12px;
            cursor: pointer;
            list-style-type: none;
            transition: all .3s ease;
            user-select: none;
        }
        .custom-menu li:hover {
            background-color: #DEF;
        }

显示:无隐藏表格。右键单击时将显示它。

然后,我需要一些JavaScript才能使其成为右键单击菜单。首先,使主菜单出现在右键菜单上:

    $(document).bind("contextmenu", function (event) {
        event.preventDefault();
        $("#main-menu").finish().toggle(100).css({
            top: event.pageY + "px",
            left: event.pageX + "px"
        });
    });

event.preventDefault()阻止默认的自定义菜单出现,而是让我的菜单出现...

现在我需要检查是否已点击<li></li>

   $("#main-menu li").click(function(){
        switch($(this).attr("data-action")) {        
            case "One": alert("One"); break;
            case "Two": alert("Two"); break;
            case "Three": alert("three"); break;
        } 
        $("#main-menu").hide(100);
    });

单击<li></li>时,此代码首先查找使用 data-action 归因于每个<li></li>的对象。然后,最后隐藏#main-menu

但是我们现在想出现一个子菜单。怎么样 ?好吧,我们只是以它的显示方式,与我们在主菜单中显示的方式相同,但是在同一位置使用以下代码:

    $("#allBlocks").finish().toggle(100).css({
            top: $("#main-menu").css("top"),
            left: $("#main-menu").css("left"),
    });

在一种情况下,我们只是插入此代码,而不是警报。在这里,我将其插入编号为 3

       $("#main-menu li").click(function(){
            switch($(this).attr("data-action")) {        
                case "One": alert("One"); break;
                case "Two": alert("Two"); break;
                case "Three": 
                    $("#subMenuOne").finish().toggle(100).css({
                        top: $("#main-menu").css("top"),
                        left: $("#main-menu").css("left"),
                    });
                    break;
            } 
            $("#main-menu").hide(100);
        });

然后,最后,我们在子菜单中将相同的点击机制置于 VOILA 。您的自定义菜单工作非常好...

这里是JSFiddle的链接,以使您更加理解。

希望这对某人有所帮助

:) f