将数据表1复制到Sheet2,以便您可以排序&编辑两个工作表(谷歌应用程序脚本?)

时间:2015-06-08 02:09:08

标签: google-apps-script google-sheets

我正在护目镜工作,并认为我需要使用谷歌应用程序脚本来做我想要的,但我是一个非营利大学医院的心理学家试图做一些好的而不是程序员(可能显示)我迫切需要帮助。我正在尝试建立一系列电子表格来跟踪我们的治疗方法参与研讨会。

1)我有一张表格“Participant_Registration”,其中输入了基本信息

2)我想将信息仅从“Participant_Registration”的前四列(A:D)传输到第二张“Learning_Sessions_Attendance”

3)我也将相同的信息转移到第三张表格' Consultation1_Attendance' - 但我需要先过滤并仅选择分配给该组的人员。

以下是指向我的电子表格副本的链接。 https://docs.google.com/spreadsheets/d/17d0bT4LZOx5cyjSUHPRFgEZTz4y1yEL_tO3gtSJ4UJ8/edit?usp=sharing

更一般地说,这就是我想要做的。这可能在谷歌应用程序脚本中?它似乎应该是。

1)我在sheet1中有原始数据

2)我希望前四列(A:D)转移到sheet2(如果我需要一个触发变量就可以了)

3)我希望它们以这样一种方式传输,即如果你对任何一张纸进行排序,数据仍然很好(仍然链接到右边的行)。

4)理想情况下,如果源表(Sheet1)中的数据发生更改,则Sheet2中将进行相同的更改。

5)理想情况下,这一切都会在没有人工干预的情况下自动发生。

任何想法?我需要你的帮助。我一直在论坛,git hub,并做了大量的搜索,并尝试了我看到的很多例子,但没有任何作用。我真的需要帮助。

以下是我的示例脚本,每个脚本都有一个问题:

//以下代码根据需要复制了从sheet1到sheet2的范围。如果我们从sheet1复制数据后,我们将数据添加到sheet2上的其他列,则会出现问题。稍后,如果我们对一些变量进行排序(人们必须这样做),如果再次部署该函数,它将覆盖数据,这意味着来自sheet1的数据未连接到sheet2上的右侧个体

function CopyRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Participant_Registration");
var range = sheet.getRange("A14:D");
var values = range.getValues();
var target = ss.getSheetByName("Learning_Sessions_Attendance");
var target_range = target.getRange("A10:D");
range.copyTo(target_range);
}

所以我再试一次。这次我试图将最后编辑的行从sheet1复制到sheet2。此功能似乎不适合我。

function CopyRow2() {
// Get Spreadsheets
var source = SpreadsheetApp.openById("1egn6pnRd6mKMGuQxX_jtgwYDtkuMUv2QJItLdh7aIEs");
var target =     SpreadsheetApp.openById("1egn6pnRd6mKMGuQxX_jtgwYDtkuMUv2QJItLdh7aIEs");

// Set Sheets
var source_sheet = source.getSheetByName("Participant_Registration");
var target_sheet = target.getSheetByName("Learning_Sessions_Attendance");


var rowIdx = source_sheet.getActiveRange().getRowIndex();
var rowValues =        source_sheet.getRange(rowIdx,1,1,source_sheet.getLastRow()).getValues();
Logger.log(rowValues);
var destValues = [];
destValues.push(rowValues[0][0]);// copy data from col A to col A
destValues.push(rowValues[0][1]);//copy data from col B to col B
destValues.push(rowValues[0][2]);//copy data from col C to col C
destValues.push(rowValues[0][3]);//copy data from col D to col D
var dest=source.getSheets()[4];
   dest.getRange(dest.getLastRow()+1,1,1,destValues.length).setValues([destValues]);//update destination sheet with selected values in the right order, the brackets are there to build the 2D array needed to write to a range
}

所以我一次又一次地尝试。我有很多例子,但似乎都没有。

非常感谢。 钱德拉

1 个答案:

答案 0 :(得分:0)

为了自动发生(一张纸的更新更新另一张纸),无论何时更换单元格,您都需要一个“事件/触发器”来运行脚本。 (即“onEdit()”函数)。

但是,由于脚本有时可能会失败(即使它们是完美的,这是因为一些Google问题),因此无法保证工作表始终包含相同的数据。

但是,如果我可以建议另一种方式,不要让ID是可选的。如果这是真实身份证件(如人员身份证号码),请专门为工作表创建另一个身份证。

我已经编辑了第二张表,显示了如何在不使用脚本的情况下执行此操作的建议。您必须注意的唯一事项是:

  • 不要创建两个具有相同ID的人。
  • 您必须在第二张表中手动插入(仅)ID。

VLOOKUP forumla将在第一张表中搜索该ID,并在同一行中返回数据。您可以以任何您喜欢的方式对任何表格进行排序。只要你不改变人们的身份证。

因此,在表2中,请在First NameLast NameEmail address中使用此内容:

 =vlookup(A10,Participant_Registration!$A:$D,2,false)
 =vlookup(A10,Participant_Registration!$A:$D,3,false)
 =vlookup(A10,Participant_Registration!$A:$D,4,false)

向下延伸此公式

我希望这会有所帮助。我会不惜一切代价避免编写脚本。这将是我最后的选择。 (如果你想重新安排你的工作表,也需要更改脚本,如果没有,他们可能会造成麻烦,写下现有数据......)

我还添加了一个按钮(插入 - 绘图)并在其中放入一个脚本(右键,单击向下箭头,“传输?脚本” - 翻译自葡萄牙语。)

如果您锁定了sheet2中的所有四列并锁定了工作表1中的ID列,则人们将无法更改ID并导致混乱。他们可以编辑工作表1中的人员而不更改工作表2中的公式。脚本不受排序或空格的影响(它会将人员添加到它找到的第一个空行中)。

我为四个列标题添加了“命名范围”。 (使用命名范围,脚本可以引用名称而不是坐标,这使您可以重新排列工作表插入和删除列,或使用 CUT 移动它们并粘贴 - 但VLOOKUP公式如果重新排列列,将需要手动更新)。

以下是代码:(如果您设法创建对话框并在该对话框中询问此人的数据,那么可能会变得更好,然后您可以锁定所有内容 - 除了添加之外,您还需要一个编辑按钮)。

function AddPerson()
{
  var S1Name = "Participant_Registration";
  var S2Name = "Learning_Sessions_Attendance";

  var ID1Name = "regID";
  var ID2Name = "learnID";

  //these vars are not used in this script
  var FN1Name = "regFirstName";
  var FN2Name = "learnFirstName";
  var LN1Name = "regLastName";
  var LN2Name = "learnLastName";
  var Email1Name = "regEmail";
  var Email2Name = "learnEmail";


  var sSheet = SpreadsheetApp.getActiveSpreadsheet();
  var Sheet1 = sSheet.getSheetByName(S1Name);
  var Sheet2 = sSheet.getSheetByName(S2Name);

  var ID1 = getRangeByName(sSheet, Sheet1.getName(), ID1Name);
  var ID2 = getRangeByName(sSheet, Sheet2.getName(), ID2Name);     Logger.log("ID2: " + ID2.getValue());

  var Empty1 = getFirstEmpty(ID1);
  var Empty2 = getFirstEmpty(ID2);

  var Biggest1 = getBiggestID(ID1);    Logger.log("Biggest 1: " + Biggest1);
  var Biggest2 = getBiggestID(ID2);    Logger.log("Biggest 2: " + Biggest2);



  if (Biggest1 !== Biggest2)
    Browser.msgBox("Warning: there are IDs in one sheet that are not in the other sheet");

  var Biggest;
  if (Biggest1 > Biggest2) Biggest = Biggest1;
  else Biggest = Biggest2;

  Biggest++;

  Empty1.setValue(Biggest);
  Empty2.setValue(Biggest);
}

function getFirstEmpty(Header)
{
  while (Header.getValue() !== "")
  {
    Header = Header.offset(1,0);
  }

  return Header;
}

function getBiggestID(Header)
{
  var Sheet = Header.getSheet();
  var LastRow = Sheet.getLastRow();

  var Values = Sheet.getRange(Header.getRow(), Header.getColumn(), LastRow - Header.getRow() + 1).getValues();

  var len = Values.length;
  var MaxID = 1;
  for (var i = 0; i < len; i++)
  {
    var val = Number(Values[i]);
    if (!isNaN(val) && val > MaxID)
      MaxID = val;
  }

  return MaxID;
}


function getRangeByName(spreadSheet, sheetName, rangeName)
{
  Logger.log("Trying range: " + "'" + sheetName + "'!" + rangeName);
  return spreadSheet.getRangeByName("'" + sheetName + "'!" + rangeName);
}