Google App 脚本对我来说 100% 有效,但其他人则不行

问题描述 投票:0回答:1

我编写了一个简单的电子表格来记录历史学会的档案条目。第一个选项卡是数据输入表单,用户可以在其中输入每条记录的详细信息。其他选项卡仅在不同视图中显示所有先前输入的记录。最后一个选项卡用作临时数据的工作选项卡。

一些脚本用于选择存档记录主题、将(表单)条目保存(添加)到电子表格行、搜索单个记录、放弃条目等。整个电子表格 100% 工作 - 对我来说!由于我们需要向数据库添加大约 1,000 条档案记录,因此我们的目标是让所有成员分担工作量。然而,每当其他人尝试输入存档记录时,他们都会收到一般“错误”(根本没有任何详细信息)。

所有用户均已接受脚本授权/运行权限。已向所有带有链接的人授予编辑访问权限,表单输入选项卡中未使用的那些单元格受到保护(以避免损坏未使用的单元格)。

选择任何表单按钮“保存”、“删除”、“退出”时,会发生运行时错误。错误有所不同,但通常会说“发生了错误”或“正在尝试编辑受保护的单元格”。没有给出错误的详细信息 - 请参阅错误图像。

示例1:[enter image description here](https://i.sstatic.net/pF1FC0fg.png)

示例2: [enter image description here](https://i.sstatic.net/WpttlAwX.png)

每个表单按钮都附有一个脚本,因此在选择按钮时会触发脚本。

“保存/更新”按钮的脚本代码:

// Function to get values from all form fields and post to the Master Archive List
// for a new entry. It will update the entry if this is a change process
function getandPostFormData()  
{                              
// Set initial settings for variables
const ss = SpreadsheetApp.getActiveSpreadsheet();
const avcWS = ss.getSheetByName('Add/View/Change');
const listWS = ss.getSheetByName('Master Archive List');
const settingsWS = ss.getSheetByName('Settings');
var CurrentRow = settingsWS.getRange("L4").getValue();  // == current row of exiating record (if one has been found)

// Check that all fields are correctly entered ...
// first all topic entries are set to non-blank.

var checkitcell = avcWS.getRange('C7'); // Check if the Topic has been selected
var checkit = checkitcell.getValue();
var checkitlength = checkit.length;

if(checkitlength == 0)
{
alertMessage('Sorry, you need to select a Main Topic for this archive item.',1);
return;
}

var checkitcell = avcWS.getRange('C8'); // Check if the Sub Topic 1 has been selected
var checkit = checkitcell.getValue();
var checkitlength = checkit.length;

if(checkitlength == 0)
{
alertMessage('Sorry, you need to select a Sub-topic 1 for this archive item.',1);
return;
}

var checkitcell = avcWS.getRange('C9'); // Check if the sub-topic 2 has been selected
var checkit = checkitcell.getValue();
var checkitlength = checkit.length;

if(checkitlength == 0)
{
alertMessage('Sorry, you need to select the last Sub-topic 2 as well.',1);
return;
}

// Check if the title has been entered
var checkitcell = avcWS.getRange('C12'); // Check if title is blank
var checkit = checkitcell.getValue();
var checkitlength = checkit.length;

if(checkitlength == 0)
{
alertMessage('Sorry, please give a Title to this archived item.',1);
return;
}

// Now check if the actual location is blank
var checkitcell = avcWS.getRange('E15'); // Check if locaton is blank
var checkit = checkitcell.getValue();
var checkitlength = checkit.length;

if(checkitlength == 0)
{
alertMessage('Sorry, the Actual Location of the archived item needs to be given.',1);
return;
}

// Check if any entry has changed for existing record and update if they have
if(settingsWS.getRange("L3").getValue() === "E")
{
    if(settingsWS.getRange("L6").getValue() != avcWS.getRange("C5").getValue())        // Status
      {listWS.getRange(CurrentRow,1).setValue(settingsWS.getRange("L6").getValue());}  
    if(settingsWS.getRange("L7").getValue() != avcWS.getRange("C7").getValue())        // Topic
      {listWS.getRange(CurrentRow,2).setValue(settingsWS.getRange("L7").getValue());}
    if(settingsWS.getRange("L8").getValue() != avcWS.getRange("C8").getValue())        // Sub 1
      {listWS.getRange(CurrentRow,3).setValue(settingsWS.getRange("L8").getValue());}
    if(settingsWS.getRange("L9").getValue() != avcWS.getRange("C9").getValue())        // Sub 2
      {listWS.getRange(CurrentRow,4).setValue(settingsWS.getRange("L9").getValue());}
    if(settingsWS.getRange("L10").getValue() != avcWS.getRange("C12").getValue())      // Title
      {listWS.getRange(CurrentRow,5).setValue(settingsWS.getRange("L10").getValue());}
    if(settingsWS.getRange("L11").getValue() != avcWS.getRange("E12").getValue())      // Description
      {listWS.getRange(CurrentRow,6).setValue(settingsWS.getRange("L11").getValue());}  
    if(settingsWS.getRange("L12").getValue() != avcWS.getRange("C14").getValue())      // Record Typr
      {listWS.getRange(CurrentRow,7).setValue(settingsWS.getRange("L12").getValue());}
    if(settingsWS.getRange("L13").getValue() != avcWS.getRange("C15").getValue())      // Location Type
      {listWS.getRange(CurrentRow,8).setValue(settingsWS.getRange("L13").getValue());}
    if(settingsWS.getRange("L14").getValue() != avcWS.getRange("E15").getValue())      // Actual Location
      {listWS.getRange(CurrentRow,9).setValue(settingsWS.getRange("L14").getValue());}

   // Now clear down the stored details just for ensuring there are no problems later
   settingsWS.getRange("L4:L14").clearContent()  // Not the record type though!
}
if(settingsWS.getRange("L3").getValue() === "N")     // New record logic ...
 {
    console.log(settingsWS.getRange("L3").getValue())
    
    // Next ID logic
    const IDCell = avcWS.getRange('C4');
    const nextIDCell = settingsWS.getRange("G3");
    var nextID = IDCell.getValue();
    IDCell.setValue(nextID); // set C4 to the next value

    // Set these cells for writing the record as they are not entered
    avcWS.getRange("C5").setValue("Live"); // set C5 record status to Live

    // Set up the array for writing / updating the entry recod
    const fieldRange = ["C5","C7","C8","C9","C12","E12","C14","C4","C15","E15"];
    const fieldValues = fieldRange.map(f => avcWS.getRange(f).getValue());

    // Now write next record in the Master Archive List tab
    listWS.appendRow(fieldValues);  // Write a new row in the Master Archive List with the new entry details / record
    nextIDCell.setValue(nextID+1);  // Add 1 to the set the next ID for the next cycle
 }

clearFormData();  // Now clear down cells and display the next ID
settingsWS.getRange("L3").setValue("N");  // Assume next entry will be a new record. It will be changed to E
                                           // when existing one searched for.

} // End of getandPostFormData function


function clearFormData()  // Function to clear the details and redisplay ID
{
  // Set initial settings for variables
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const avcWS = ss.getSheetByName('Add/View/Change');
  const settingsWS = ss.getSheetByName('Settings');
  const IDCell = avcWS.getRange('C4');
  const nextIDCell = settingsWS.getRange("G3").getValue();
  const fieldRange = ["C5","C7","C8","C9","C12","E12","C14","C4","C15","E15","E4"];
  fieldRange.forEach(f => avcWS.getRange(f).clearContent());  // Clear all cells

  // Redisplay the next ID
  IDCell.setValue(nextIDCell); // set C4 to the next value ready for next input cycle

}  // End of function to clear the form details for the next entry cycle

“退出”按钮的脚本代码:

// Function when the Exit button is pressed.
function ExitForm()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var avcWS = ss.getSheetByName('Add/View/Change');
var listWS = ss.getSheetByName('Master Archive List');
var settingsWS = ss.getSheetByName('Settings');
var changed = "N";   // Used to denote some field has been changed

// Anything changed?
if(settingsWS.getRange("L6").getValue() != avcWS.getRange("C5").getValue())        // Status
  {changed ="Y";}  
if(settingsWS.getRange("L7").getValue() != avcWS.getRange("C7").getValue())        // Topic
  {changed ="Y";}
if(settingsWS.getRange("L8").getValue() != avcWS.getRange("C8").getValue())        // Sub 1
  {changed ="Y";}
if(settingsWS.getRange("L9").getValue() != avcWS.getRange("C9").getValue())        // Sub 2
  {changed ="Y";}
if(settingsWS.getRange("L10").getValue() != avcWS.getRange("C12").getValue())      // Title
  {changed ="Y";}
if(settingsWS.getRange("L11").getValue() != avcWS.getRange("E12").getValue())      // Description
  {changed ="Y";}  
if(settingsWS.getRange("L12").getValue() != avcWS.getRange("C14").getValue())      // Record Typr
  {changed ="Y";}
if(settingsWS.getRange("L13").getValue() != avcWS.getRange("C15").getValue())      // Location Type
  {changed ="Y";}
if(settingsWS.getRange("L14").getValue() != avcWS.getRange("E15").getValue())      // Actual Location
  {changed ="Y";}

if(settingsWS.getRange("L3").getValue() == "N" && changed == "Y")  // This is a new entry being abandoned.
                                                                    // Note stored fields will be blank
  {
   if(alertMessage('You appear to have started to enter a new entry. Abandon it?',2) == "Y")
     {clearFormData();
   }
  }

if(settingsWS.getRange("L3").getValue() == "E" && changed == "Y")  // This is an existing that has changed being abandoned.
                                                                    // Note stored fields will be original entry
  {
  if(alertMessage('You appear to have abandoned changes to an existing entry. Abandon it?',2) == "Y")
    {clearFormData();}
  }

  if(changed == "N")    // As nothing has changed, simply clear form data and start again for the next cycle
    {
      clearFormData()
    // Now clear down the stored details just for ensuring there are no problems later
      settingsWS.getRange("L4:L14").clearContent()  // Not the record type though!
      settingsWS.getRange("L3").setValue("N");  // Assume next entry will be a new record.
    }

} // end of Exit function

“删除”按钮的脚本代码。

// Function when button Delete / Reinstate has been pressed.
function DeleteReinstate()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var avcWS = ss.getSheetByName('Add/View/Change');
var listWS = ss.getSheetByName('Master Archive List');
var settingsWS = ss.getSheetByName('Settings');

if(settingsWS.getRange("L3").getValue() == "N")  // Cannot delete / reinstate an entry that has not been created!!
{
  alertMessage('You cannot delete or reinstate an entry that has not been fully entered, yet.',1)
  return;
}

if(settingsWS.getRange("L3").getValue() == "E" && settingsWS.getRange("L6").getValue() == 'Live')  // existing & live
{
  if(alertMessage('Are you sure you want to change the Status to deleted?',2) == "Y")
    {
      avcWS.getRange("C5").setValue('Deleted Entry');  // Update form cell
      settingsWS.getRange("L6").setValue('Deleted Entry');  // Then tempory store
      listWS.getRange(settingsWS.getRange("L4").getValue(),1).setValue('Deleted Entry');  // and in record row too
      return;
    }
} else {  // existing & deleted
  if(alertMessage('Are you sure you want to change the Status back to Live?',2) == "Y")
    {
      avcWS.getRange("C5").setValue('Live');  // Update form cell
      settingsWS.getRange("L6").setValue('Live');  // Then tempory store
      listWS.getRange(settingsWS.getRange("L4").getValue(),1).setValue('Live');  // and in record row too
    }


} // end of Deleted / reinstatefunction

完整的电子表格

下面是我的电子表格的两个版本。

1.) 已填写记录条目的电子表格,但就在我以外的任何用户选择“保存/更新”按钮时出错之前。

https://docs.google.com/spreadsheets/d/1TLRKkEg0OqUwzsXOkNDDPxA7BKDNb5I5qtx4M-6SWsM/edit?usp=sharing

2.) 包含一个条目的电子表格已成功添加到主数据库并通过其他选项卡可见。

https://docs.google.com/spreadsheets/d/14quMCj5NSweaG7c0jXTOe8ZkMy5aCXF-LOaFZ6V328A/edit?usp=sharing

警告。我还有一个单独的问题需要解决。我使用一组级联下拉菜单来选择任何条目的主题和子主题。选择主要主题可确定子主题的下拉列表,类似地也可确定子主题 2 下拉列表。然而,由于某种原因,在选择第二个(或第三个)下拉菜单之前,必须等待(很长一段时间)Google Sheets 完成其“保存”和“保存到驱动器”周期,否则会破坏选择。这一切都是由我的简单应用程序脚本控制的。 Google 速度太慢,无法进行第二次下拉选择,我目前不知道为什么。

有谁知道为什么只有我可以运行电子表格以及如何让其他人使用它?我曾尝试寻找这个问题但找不到答案。感谢所有帮助。

google-sheets google-apps-script spreadsheet-protection
1个回答
0
投票

在受保护的工作表和范围上添加另一个范围

您遇到的错误是因为单元格

C4
C5
protected
。要解决此问题,请按照以下步骤操作。


步骤:

1.) 在电子表格上,右键单击

Add/View/Change
并选择
Protect Sheet

Protect sheet

2.) 单击

Set Permissions

3.) 从那里,单击

BLHS Users
Add another range

4.) 添加

C4
C5

它应该看起来像这样:

Sample

5.) 单击

Done


参考资料:

© www.soinside.com 2019 - 2024. All rights reserved.