在编辑之前从值中获取富文本的 URL

Obtain URL from richtext from value before edit

提问人:LionelHutz 提问时间:10/3/2023 最后编辑:LionelHutz 更新时间:10/6/2023 访问量:104

问:

我的脚本的 F 列已激活日期验证(短日期)。 F 列中的所有单元格都包含带有日历事件 URL 的富文本:

enter image description here

每次编辑列 F(= 设置为新日期)时,我都希望我的脚本访问日历事件,并将其更新为新日期。 (这不是我问题的一部分,但解释了我最终想要实现的目标)。 编辑:这是我的整个脚本:

function DateEdit(e) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var editedRange = e.range;
  var editedColumn = editedRange.getColumn();
  
  if (editedColumn == 6) {

  // Get event URL
      var orgNumberFormats = editedRange.getNumberFormats();
      editedRange.setNumberFormat("@");
      var richTextValue = editedRange.getRichTextValue();
      editedRange.setNumberFormats(orgNumberFormats);
      var eventUrl = richTextValue.getLinkUrl();

      // Get event ID
      if (eventUrl) {
        var eventIdEncoded = eventUrl.split("/").pop(); // Get the encoded part from the URL
        try {
          eventIdEncoded = eventIdEncoded.replace(/-/g, '+').replace(/_/g, '/'); // Revert URL-safe Base64 encoding
          eventIdEncoded += "==".substring(0, 2 - eventIdEncoded.length % 2); // Add padding if needed
          var eventIdDecoded = Utilities.base64Decode(eventIdEncoded);
          
          var eventId = Utilities.newBlob(eventIdDecoded).getDataAsString();
          var decodeEventId = eventId.split(" ")[0];
    
        } catch (e) {
          Logger.log("Error decoding and extracting the event ID: " + e);
        }
      } else {
        Logger.log("Cell contains no URL.");
      }

    // Edit Event
    try {
      var newDateStr = editedRange.getValue(); // Assuming the date is in "dd/mm/yyyy" format

      // Split the date string into parts
      var dateParts = newDateStr.split('/');
      var day = dateParts[0];
      var month = dateParts[1];
      var year = dateParts[2];

      // Create a new Date object with the adjusted date
      var newDate = new Date(year, month - 1, day); // Subtract 1 from the month because months are zero-based
  
      if (!isNaN(newDate.getTime())) {
        // The date string was successfully converted to a Date object
        // Now, you can proceed with your code to update the event date

        Logger.log("Event ID: " + decodeEventId)
  
        var calendarId = '[email protected]'; // Replace with your calendar ID
        var calendar = CalendarApp.getCalendarById(calendarId);
        var event = calendar.getEventById(decodeEventId);
  
        if (event) {
          // Get the existing start and end times
          var startTime = event.getStartTime();
          var endTime = event.getEndTime();
  
          // Create new Date objects with the adjusted date but the same time
          var newStartTime = new Date(newDate);
          newStartTime.setHours(startTime.getHours(), startTime.getMinutes());
  
          var newEndTime = new Date(newDate);
          newEndTime.setHours(endTime.getHours(), endTime.getMinutes());
  
          // Update the event's start and end times with the new date
          event.setTime(newStartTime, newEndTime);


Logger.log("Event date updated successfully, and guests have been notified.");
        } else {
          Logger.log("Event not found with ID: " + decodeEventId);
        }
      } else {
        Logger.log("Invalid date format in the edited cell: " + newDateStr);
      }
    } catch (e) {
      Logger.log("Error updating event with ID: " + decodeEventId + "\n" + e.toString());
    }
  }
}

问题是,如果不使用日期选择器,富文本中的 URL 可能会被其他用户覆盖和删除。我还没有找到在富文本中保留 URL 的方法。我可以获取编辑前的旧值 (e.oldValue),但不能获取 URL。

我需要我的脚本来获取URL,并在更改日期后将其作为RTF放回单元格(默认情况下,因为其他用户是否使用日期选择器或输入与给定验证格式匹配的手动日期并不重要)。

URL 不会更改,因为日历事件保持不变。

非常感谢任何帮助,提前致谢!

google-apps-script google-sheets datepicker rtf

评论

0赞 Serenity 10/4/2023
我可以知道您如何在日期中添加链接吗?您使用 HYPERLINK 还是通过 Appscript?
0赞 Tanaike 10/4/2023
虽然我不确定我是否能正确理解你的问题,但我提出了一个示例脚本作为答案。请确认。如果我误解了你的问题,这没有用,我深表歉意。
0赞 LionelHutz 10/4/2023
@Serenity如上所述,我使用 richtextbuilder,而不是超链接。

答:

1赞 Tanaike 10/4/2023 #1

虽然我不确定我是否能正确理解您的问题,但以下示例脚本怎么样?

示例脚本:

请将以下脚本复制并粘贴到 Google 电子表格的脚本编辑器中。并且,请设置 .sheetName

首先,请运行函数。这样,列“F”的当前单元格的 URL 将保存到 PropertiesService。init()

下一步,请手动修改电子表格中“F”列的值。这样,由简单的触发器自动运行。并且,URL 设置为编辑后的单元格。onEdit

const sheetName = "Sheet1"; // Please set your sheet name.

// First, please run this function.
function init() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  const urls = sheet.getRange("F1:F" + sheet.getLastRow()).getRichTextValues().map(([f]) => f.getLinkUrl() || "");
  PropertiesService.getScriptProperties().setProperty("urls", JSON.stringify(urls));
}

function onEdit(e) {
  const { range } = e;
  const sheet = range.getSheet();
  if (sheet.getSheetName() != sheetName || range.columnStart != 6) return;
  const prop = PropertiesService.getScriptProperties();
  const propUrls = prop.getProperty("urls");
  const urls = propUrls ? JSON.parse(propUrls) : [];
  const url = urls[range.rowStart - 1];
  const currentUrl = range.getRichTextValue().getLinkUrl();
  if (currentUrl) {
    urls[range.rowStart - 1] = currentUrl;
    prop.setProperty("urls", JSON.stringify(urls));
  } else if (url) {
    range.setRichTextValue(range.getRichTextValue().copy().setLinkUrl(url).build());
  }
}

重要:

  • 在此脚本中,它假定列“F”的 URL 是常量。如果添加并更新了“F”列的 URL,请运行该函数。这样,PropertiesService 中的 URL 也会更新。init()

注意:

  • 此示例脚本是 的简单示例脚本。请小心这一点。I need my script to obtain the URL & put it back to the cell as RTF after the date was changed

  • Google Apps 脚本的属性服务规范可以在此报告中看到(作者:我)。如果您的情况超出了 Properties Service 的当前规范,则可能需要使用临时电子表格。

引用:

评论

0赞 LionelHutz 10/4/2023
非常感谢您的回复。对不起,如果我的问题写得不够清楚。我正在使用可安装的触发器,基本上我试图实现的只是保留富文本中的 URL,即使用户手动覆盖日期并删除 URL。我认为实现这一目标的唯一解决方案是以某种方式将旧的 URL 值存储在脚本中,但是一旦单元格值被覆盖,我就找不到获取旧 URL 的方法。我理解您对 INIT() 函数的想法,但我需要一些不需要手动执行且带有触发器的东西。
0赞 Tanaike 10/4/2023
@LionelHutz 感谢您的回复。对于给您带来的不便,我深表歉意。而且,我担心当我看到您的回复时,我认为我的示例脚本可以达到您的预期结果。关于,如果要自动保存URL,通过触发器执行函数怎么样?I understand your idea with the INIT() function, but I would need something that doesn't need manual execution and comes with the trigger.init
0赞 Tanaike 10/4/2023
@LionelHutz关于,我认为我的剧本可以做到这一点。关于,我认为我的脚本是由简单触发器的 OnEdit 触发器自动运行的。如果我的回答对您的情况没有用,我深表歉意。届时,你能提供更多关于我的答复问题的信息吗?通过这一点,我想确认一下。I just can't find a way to obtain the old URL once the cell value has been overwrittenbut I would need something that doesn't need manual execution and comes with the trigger.
0赞 Tanaike 10/4/2023
@LionelHutz 顺便说一句,函数用于保存“F”列中的当前URL。 函数在编辑列“F”时自动运行。我认为这可以通过我的示例脚本来实现。但是,我的脚本是一个简单的脚本。如果我的回答没有用,我深表歉意。initonEditbasically all I try to achieve is that the URL in the richtext will be preserved, even if a user overwrites the date manually, removing the URL.
0赞 LionelHutz 10/4/2023
非常感谢您的回复。我不确定我是否正确地关注了你。如果我使用 onEdit 触发器运行 INIT() 函数,已经太晚了,因为此时富文本可能已经被覆盖了。你认为我可以用一个简单的 onSelectionChange() 触发器解决这个问题吗?因为必须先由用户选择单元格,然后才能更改值。我认为这可能是解决它的最简单方法。