【问题标题】:Shift Cell Range in Google Sheets在 Google 表格中移动单元格范围
【发布时间】:2017-02-16 20:45:11
【问题描述】:

我正在尝试获取一系列单元格并将它们全部向右移动一个单元格。我希望这种情况每周自动发生一次。我知道在脚本编辑器中我可以创建一个触发器,让它每周安排一次,但我不确定如何编写代码。

如果有人可以帮助提供一个代码,让我可以指示哪个 SHEET 和 CELL RANGE 向右移动一个单元格,我将不胜感激。

基本上,我想要完成的是跟踪数周的数据。每周都会更新表格,我希望旧数据右移一个,基本上表明数据已经旧了一周。

此外,我只尝试将数据保留 6 周,因此数据不会永远持续。

举个例子:A 列 = 当前周(手动更新)。 B-F 列 = 前几周(1-5 周前)。

每周一次,应将 A-E 列中的数据右移 1 以保留数据。班次后,A 列中的数据将手动更新以表示当前周。这将导致显示当前一周的数据和另外 5 周的数据......总共 6 周的数据。

如果可能的话,如果有办法在排除标题行而不是范围的情况下仅移动列,我会很感兴趣。

【问题讨论】:

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


    【解决方案1】:

    可以试试这样的吗?

    function myFunction() {
       var ss = SpreadsheetApp.getActiveSpreadsheet();
     var sheet = ss.getSheets()[0];
    
     // This inserts 1 columns before the first column
     sheet.insertColumnsBefore(1, 1);
      
      // labels the weeks static
          ss.getRange('A1').setFontWeight("bold").setValue("Week1").setBackground("#BBBBBB");
          ss.getRange('B1').setFontWeight("bold").setValue("Week2").setBackground("#BBBBBB");
          ss.getRange('C1').setFontWeight("bold").setValue("Week3").setBackground("#BBBBBB");
          ss.getRange('D1').setFontWeight("bold").setValue("Week4").setBackground("#BBBBBB");
          ss.getRange('E1').setFontWeight("bold").setValue("Week5").setBackground("#BBBBBB");
           ss.getRange('F1').setFontWeight("bold").setValue("Week6").setBackground("#BBBBBB");
    }

    【讨论】:

    • 这是个好主意。这样您就不必担心复制数据。
    • 这可能是一个不错的解决方案,但是它会移动计算单元格值的公式。如果它只是移动显示的值而不是移动单元格时的公式会更有帮助。
    【解决方案2】:

    复制或剪切并粘贴

    根据您的最后评论,我决定为您提供另一个解决方案。此解决方案将复制或剪切并粘贴任何工作表中的任何数据范围到具有相同尺寸的任何其他范围。范围可以在同一页面或不同页面上,并且范围可以重叠。此外,一旦您复制了一个范围,文档将记住源和目标范围,以便您可以再次复制或剪切和粘贴它们,而无需设置范围。如果您想更改范围,只需运行例程,它会让您选择清除范围,然后您可以再次运行它,它会记住新的范围。 菜单上的复制和剪切选择运行例程。显示属性选项显示您当前的设置。清除范围只会删除 DocumentProperties 中的所有内容。

    但“复制和剪切”选项将为您提供所有相同的信息。

    function onOpen()
    {
      var ui = SpreadsheetApp.getUi();
      ui.createMenu('My Tools')
            .addItem('Copy or Cut', 'copyFromToSetupUi')
            .addItem('Display Properties','dispProperties')
            .addItem('Clear Ranges','clearCopyProperties')
            .addToUi();
    }
    
    function dispProperties()
    {
      var copyProperties = PropertiesService.getDocumentProperties();
      var srcShtNameStr = copyProperties.getProperty('SourceSheetName');
      var srcShtRangeStr = copyProperties.getProperty('SourceSheetRange');
      var desShtNameStr = copyProperties.getProperty('DestinationSheetName');
      var desShtRangeStr = copyProperties.getProperty('DestinationSheetRange');
      var title = 'Copy From To Sheets Properties';
      var msg = 'Source Sheet Name = ' + srcShtNameStr + '<br />';
      msg += 'Source Sheet Range = ' + srcShtRangeStr + '<br />';
      msg += 'Destination Sheet Range = ' + desShtNameStr + '<br />';
      msg += 'Destination Sheet Range = ' + desShtRangeStr + '<br />';
      msg += '<input type="button" value="Exit" onClick="google.script.host.close();" />';
      dispStatus(title,msg);
    }
    
    function copyFromToSheets()
    {
      var copyProperties = PropertiesService.getDocumentProperties();
      var srcRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('SourceSheetName')).getRange(copyProperties.getProperty('SourceSheetRange'));
      var srcA = srcRange.getValues();
      srcRange.setBackground('#ffffff');
      var desRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('DestinationSheetName')).getRange(copyProperties.getProperty('DestinationSheetRange'));
      desRange.setValues(srcA);
      desRange.setBackground('#ffffff');
    }
    
    function cutnpasteFromToSheets()
    {
      var copyProperties = PropertiesService.getDocumentProperties();
      var srcRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('SourceSheetName')).getRange(copyProperties.getProperty('SourceSheetRange'));
      var srcA = srcRange.getValues();
      srcRange.clearContent();
      srcRange.setBackground('#ffffff');
      var desRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(copyProperties.getProperty('DestinationSheetName')).getRange(copyProperties.getProperty('DestinationSheetRange'));
      desRange.setValues(srcA);
      desRange.setBackground('#ffffff');
    }
    
    function setCopySource()
    {
      var srcShtName = SpreadsheetApp.getActiveSheet().getName();
      var srcShtRange = SpreadsheetApp.getActiveRange();
      var copyProperties = PropertiesService.getDocumentProperties();
      copyProperties.setProperty('SourceSheetRange', srcShtRange.getA1Notation());
      copyProperties.setProperty('SourceSheetName', srcShtName);
      srcShtRange.setBackground('#d9caa9');
    }
    
    function setCopyDestination()
    {
      var desShtName = SpreadsheetApp.getActiveSheet().getName();
      var desShtRange = SpreadsheetApp.getActiveRange();
      var copyProperties = PropertiesService.getDocumentProperties();
      copyProperties.setProperty('DestinationSheetRange',desShtRange.getA1Notation());
      copyProperties.setProperty('DestinationSheetName', desShtName);
      desShtRange.setBackground('#c4df87');
    }
    
    function clearCopyProperties()
    {
      var copyProperties = PropertiesService.getDocumentProperties();
      var srcShtNameStr = copyProperties.getProperty('SourceSheetName');
      var srcShtRangeStr = copyProperties.getProperty('SourceSheetRange');
      var desShtNameStr = copyProperties.getProperty('DestinationSheetName');
      var desShtRangeStr = copyProperties.getProperty('DestinationSheetRange');
      if(srcShtNameStr && srcShtRangeStr)
      {
        var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
        srcShtRange.setBackground('#ffffff');
      }
      else
      {
        SpreadsheetApp.getUi().alert('At least one of the Source String Properties is undefined in clearCopyProperties so background color cannot be reset.');
      }
      if(desShtNameStr && desShtRangeStr)
      {
        var desShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRangeStr);
        desShtRange.setBackground('#ffffff');
      }
      else
      {
        SpreadsheetApp.getUi().alert('At least one of the Destination String Properties is undefined in clearCopyProperties so background color cannot be reset.');
      }
      copyProperties.setProperty('SourceSheetName', '');
      copyProperties.setProperty('SourceSheetRange', '');
      copyProperties.setProperty('DestinationSheetName', '');
      copyProperties.setProperty('DestinationSheetRange', '');
    }
    
    function copyFromToSetupUi()
    {
      var copyProperties = PropertiesService.getDocumentProperties();
      var srcShtNameStr = copyProperties.getProperty('SourceSheetName');
      var srcShtRangeStr = copyProperties.getProperty('SourceSheetRange');
      var desShtNameStr = copyProperties.getProperty('DestinationSheetName');
      var desShtRangeStr = copyProperties.getProperty('DestinationSheetRange');
      var title='No Title';
      var msg = 'No Text';
      if(!srcShtNameStr || !srcShtRangeStr )  //if !src
      {
        title = 'Select Source Range';
        msg = '<p>Please select input range from <strong>Source Sheet.</strong> and then press "Source Range Selected" button below.</p>\
        <br /><input type="button" value="Source Range Selected" onclick="google.script.run.copyFromToSetupHelper(1);google.script.host.close();" />';
        msg += '<script>console.log(\'flag1\');</script>';
        dispStatus(title, msg);
      }
      if ((srcShtNameStr && srcShtRangeStr) && (!desShtNameStr || !desShtRangeStr)) //if src and !des
      {
          var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
          title = 'Select Destination Range';
          msg = '<p>Please select a destination range which is ' + srcShtRange.getNumRows() + ' rows by ' + srcShtRange.getNumColumns() + ' columns.</p>';
          msg += '<br /><input type="button" value="Destination Range Selected" onclick="google.script.run.copyFromToSetupHelper(2);google.script.host.close();" />';
          msg += '<br />Input Range: ' + srcShtRangeStr + '<br /><input type="button" value="Clear Ranges and Start Over" onClick="google.script.run.clearCopyProperties();google.script.host.close(); />';
          dispStatus(title, msg);
      }
      if((srcShtNameStr && srcShtRangeStr) && (desShtNameStr && desShtRangeStr))//if src and des
      {
        var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
        var desShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRangeStr);
        if((desShtRange.getWidth()===srcShtRange.getWidth()) && (desShtRange.getHeight()===srcShtRange.getHeight()))
        {
          title= 'Displaying Source and Destination Ranges';
          msg = '<br />Source Sheet/Range: ' + srcShtNameStr + '/' + srcShtRangeStr + '<br />Destination Sheet/Range: ' + desShtNameStr + '/' + desShtRangeStr + '<br />';
          msg += '<br /><input type="button" value="Perform Copy" onclick="google.script.run.copyFromToSheets();google.script.host.close();" />';
          msg += '<br /><input type="button" value="Perform Cut & Paste" onclick="google.script.run.cutnpasteFromToSheets();google.script.host.close();" />';
          msg += '<br /><input type="button" value="Keep both Ranges Defined" onclick="google.script.host.close();" />';
          msg += '<br /><input type="button" value="Clear Ranges and Start Over" onclick="google.script.run.clearCopyProperties();google.script.host.close();" />';
          dispStatus(title,msg);
        }
        else
        {
          var srcShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(srcShtNameStr).getRange(srcShtRangeStr);
          var desShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRangeStr);
          var newdesShtRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(desShtNameStr).getRange(desShtRange.getRow(), desShtRange.getColumn(), srcShtRange.getNumRows(), srcShtRange.getNumColumns());
          desShtRange.setBackground('white');
          newdesShtRange.setBackground('#c4df87');
          copyProperties.setProperty('DestinationSheetRange', newdesShtRange.getA1Notation());
          title = 'Destination Range Adjusted';
    
          msg = 'Source Range and Destination Range Dimension did not Match. So it was assumed that the upper left corner of the Destination Range is correct';
          msg += 'and that the Sheet Selections were correct. The Destination Range was modified to have the same dimensions as the Source Range. ';
          msg += '<br />Source Sheet/Range: ' + srcShtNameStr + '/' + srcShtRangeStr + '<br />Destination Sheet/Range: ' + desShtNameStr + '/' + newdesShtRange.getA1Notation() + '<br />';
          msg += '<br /><input type="button" value="Perform Copy" onclick="google.script.run.copyFromToSheets();google.script.host.close();" />';
          msg += '<br /><input type="button" value="Perform Cut & Paste" onclick="google.script.run.cutnpasteFromToSheets();google.script.host.close();" />';
          msg += '<br /><input type="button" value="Keep both Ranges Defined" onclick="google.script.host.close();" />';
          msg += '<br /><input type="button" value="Clear Ranges and Start Over" onclick="google.script.run.clearCopyProperties();;google.script.host.close(); />';
          dispStatus(title,msg);
    
        }
    
    
      }
    }
    
    
    function copyFromToSetupHelper(mode)
    {
      var mode = (typeof(mode) !== 'undefined')? mode : 0;
      switch(mode)
      {
        case 1:
          setCopySource();
          copyFromToSetupUi();
          break;
        case 2:
          setCopyDestination();
          copyFromToSetupUi();
          break;
        default:
          clearCopyProperties();
      }
    }
    // Display a modeless dialog box with custom HtmlService content.
    function dispStatus(title,html,width,height)
    {
      var title = typeof(title) !== 'undefined' ? title : 'No Title Provided';
      var width = typeof(width) !== 'undefined' ? width : 400;
      var height = typeof(height) !== 'undefined' ? height : 300;
      var html = typeof(html) !== 'undefined' ? html : '<p>No html provided.</p>';
      var htmlOutput = HtmlService
         .createHtmlOutput(html)
         .setWidth(width)
         .setHeight(height);
     SpreadsheetApp.getUi().showModelessDialog(htmlOutput, title);
    } 
    

    【讨论】:

      【解决方案3】:

      Google 脚本:向任意方向移动活动选择范围

      这会将任何选定范围移动到您希望的任何方向,并且可以选择目标范围作为活动选择。到目前为止,我只尝试过一步移动。
      function rangeJog(hoffset,voffset,moveselection)
      {
        var hoffset = (typeof(hoffset) !== 'undefined')? hoffset : 1;
        var voffset = (typeof(voffset) !== 'undefined')? voffset : 0;
        var moveselection = (typeof(moveselection) != 'undefined')? moveselection : true;
        var src = SpreadsheetApp.getActiveRange();
        var srcA1 = src.getA1Notation();
        var row = src.getRow() + voffset;
        var col = src.getColumn() + hoffset; 
        var rows = src.getLastRow() - src.getRow() + 1; 
        var cols = src.getLastColumn() - src.getColumn() +1;  
        
        if((row<1) || (col<1))
        {
          //dispStatus('No More Room to Move','<p>Either the first row or the first column or both will be less than one. <input type="button" value="exit" onClick="google.script.host.close();" /></p>', 400, 200);
          SpreadsheetApp.getUi().alert('No more room to move.');
        }
        else
        {
          var des = SpreadsheetApp.getActiveSheet().getRange(src.getRow() + voffset, src.getColumn() + hoffset, src.getLastRow() - src.getRow() + 1, src.getLastColumn() - src.getColumn() +1);
          var srcA = src.getValues();
          src.clearContent();
          des.setValues(srcA);
          if(moveselection)
          {
            SpreadsheetApp.getActiveSheet().setActiveSelection(des);
          }
        }
        var end = "is near";
      }
      

      它现在适用于选定的范围,但任何范围都可以工作,因为所有计算都是相对于 src 范围的。如果 moveselection 为真,我还对其进行了修改以移动选择。

      但是在左边插入一个新列的想法可能是一种更简单的方法。虽然我没有看到任何插入单元格命令,但插入列也会移动标题。

      【讨论】:

      • 这似乎是一个很好的解决方案,但是当我运行它时,它只会移动我选择的单元格。是否可以设置移动的范围,例如 D2:H13 ?
      • 如果你的意思是我可以设置它,以便它每次都从同一个源移动到同一个目的地,直到你更改设置,答案是肯定的。我唯一想知道的是你想让我做这一切吗?或者你想学习如何自己学习如何做吗?无论哪种方式我都可以,尽管第二种选择需要更多时间,因为我已经完成了,除了一小部分可能会在那时完成你读过这个。
      • 感谢库珀的回复。如果您能简单地提供一个代码供我使用,我将不胜感激,我需要做的就是更新我想要移动的范围。提供的代码运行良好,但我必须选择一个范围。我更愿意在脚本代码中简单地指出范围是什么(即 D2:H13),然后为脚本设置一个触发器,使其每周运行一次。如果您能够提供代码并简单地指出要更改哪个部分以更新 Range,我将不胜感激。 :)
      • 如果您使用标题为“复制”或“剪切并粘贴”的答案,那么它会记住最后一次操作,直到您选择“清除范围并重新开始”按钮。在目标范围内您拥有的所有内容要做的是点击“to”范围的左上角和角落,它会自动计算并突出显示范围的其余部分。