javascript - 如何在邮件合并中保留 google 电子表格的格式?

标签 javascript google-apps-script google-sheets

我想发送一封电子邮件,其中包含谷歌电子表格内容作为带格式的正文。我引用了 here但它只适用于单元格“A1”,我希望它适用于完整的数据范围。如何在发送电子邮件时保留所有格式?

enter image description here

最佳答案

您需要使用getRichTextValues 获取给定范围内每个单元格的所有富文本值,然后迭代每个值。然后将它们编译成表格。

此外,由于脚本不包含背景,所以我也添加了它。请参阅下面的工作脚本、示例数据和输出。

脚本修改:

const sendRichEmail = () => {
  // update cellAddress if needed, or use getDataRange below instead.
  const cellAddress = 'A1:B2';
  const sheetName = 'Mail Merge';
  const recipient = 'test@email.com';

  const richTextValue = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName(sheetName)
    .getRange(cellAddress)
    .getRichTextValues();

  // Adding background color
  const backgroundColors = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName(sheetName)
    .getRange(cellAddress)
    .getBackgrounds();

  /* Run is a stylized text string used to represent cell text.
     This function transforms the run into HTML with CSS
   */
  const getRunAsHtml = (richTextRun) => {
    const richText = richTextRun.getText();

    // Returns the rendered style of text in a cell.
    const style = richTextRun.getTextStyle();

    // Returns the link URL, or null if there is no link
    // or if there are multiple different links.
    const url = richTextRun.getLinkUrl();

    const styles = {
      color: style.getForegroundColor(),
      'font-family': style.getFontFamily(),
      'font-size': `${style.getFontSize()}pt`,
      'font-weight': style.isBold() ? 'bold' : '',
      'font-style': style.isItalic() ? 'italic' : '',
      'text-decoration': style.isUnderline() ? 'underline' : '',
    };

    // Gets whether or not the cell has strike-through.
    if (style.isStrikethrough()) {
      styles['text-decoration'] = `${styles['text-decoration']} line-through`;
    }

    const css = Object.keys(styles)
      .filter((attr) => styles[attr])
      .map((attr) => [attr, styles[attr]].join(':'))
      .join(';');

    const styledText = `<span style='${css}'>${richText}</span>`;
    return url ? `<a href='${url}'>${styledText}</a>` : styledText;
  };

  // Format the data that will work on multiple cells. 
  // Edit table properties if needed
  var finalBody = `<html><body><table border='1px'>`;
  /* Returns the Rich Text string split into an array of runs,
  wherein each run is the longest possible
  substring having a consistent text style. */
  for (var i = 0; i < richTextValue.length; i++) {
    finalBody += '<tr>';
    for (var j = 0; j < richTextValue[i].length; j++) {
      finalBody += `<td bgcolor='${backgroundColors[i][j]}'>`;
      finalBody += richTextValue[i][j].getRuns().map((run) => getRunAsHtml(run)).join('');
      finalBody += '</td>';
    }
    finalBody += '</tr>';
  }
  finalBody += '</table></body></html>';

  MailApp.sendEmail({to: recipient, subject: 'Rich HTML Email', htmlBody: finalBody});
};

示例数据:

sample

输出:

output

备注:

  • 我还对其进行了格式化,将数据作为表格发送。如果需要,请随意修改表的属性。
  • 要减少单元格之间的间距,请使用:

单元格间距 0:

var finalBody = `<html><body><table border='1' cellspacing='0'>`;

输出:

output2

引用:

编辑:

  • 这是 getRichTextValues 对日期对象和数字的限制。或者,您可以使用 getDisplayValues 插入这些值,但由于 getTextStyles 不返回任何内容,因此不会有正确的文本样式。

issue

修改后的脚本:

const sendRichEmail = () => {
  const sheetName = 'Sheet1';
  const recipient = 'test@email.com';

  const richTextValue = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName(sheetName)
    .getDataRange()
    .getRichTextValues();

  // get string equivalent of the data
  const values = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName(sheetName)
    .getDataRange()
    .getDisplayValues();

  const backgroundColors = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName(sheetName)
    .getDataRange()
    .getBackgrounds();

  // pass the current index of row and column
  const getRunAsHtml = (richTextRun, i, j) => {
    var richText = richTextRun.getText();
    // if richText is empty, assign value from getDisplayValues
    if (!richText)
      richText = values[i][j];
    const style = richTextRun.getTextStyle();
    const url = richTextRun.getLinkUrl();

    const styles = {
      color: style.getForegroundColor(),
      'font-family': style.getFontFamily(),
      'font-size': `${style.getFontSize()}pt`,
      'font-weight': style.isBold() ? 'bold' : '',
      'font-style': style.isItalic() ? 'italic' : '',
      'text-decoration': style.isUnderline() ? 'underline' : '',
    };

    if (style.isStrikethrough()) {
      styles['text-decoration'] = `${styles['text-decoration']} line-through`;
    }

    const css = Object.keys(styles)
      .filter((attr) => styles[attr])
      .map((attr) => [attr, styles[attr]].join(':'))
      .join(';');

    const styledText = `<span style='${css}'>${richText}</span>`;
    return url ? `<a href='${url}'>${styledText}</a>` : styledText;
  };

  var finalBody = `<html><body><table border='1px'>`;
  for (var i = 0; i < richTextValue.length; i++) {
    finalBody += '<tr>';
    for (var j = 0; j < richTextValue[i].length; j++) {
      finalBody += `<td bgcolor='${backgroundColors[i][j]}'>`;
      // pass i and j into getRunAsHtml
      finalBody += richTextValue[i][j].getRuns().map((run) => getRunAsHtml(run, i, j)).join('');
      finalBody = finalBody.replace(/\n/g, '<br>');
      finalBody += '</td>';
    }
    finalBody += '</tr>';
  }
  finalBody += '</table></body></html>';


  MailApp.sendEmail({ to: recipient, subject: 'Rich HTML Email', htmlBody: finalBody });
};

输出:

output

关于javascript - 如何在邮件合并中保留 google 电子表格的格式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70930781/

相关文章:

javascript - 哪种注释格式适用于带有注释的 TypeScript?

javascript - 在 mapDispatchToProps 中传递事件对象和参数

javascript:href 链接在 iPhone 中不起作用

google-apps-script - Google 文档中的标题部分

google-apps-script - SpreadsheetApp.getUi() 故障,警告框、提示框不出现

javascript - 完全检测另一个物体内部的物体

google-apps-script - 如何通过 Google Apps Script 获取 Google Drive 文件的 "shareable link"?

google-apps-script - Google Sheet 用于 Firestore 多个文档

google-apps-script - 如何将格式化文本转换为 Google-apps-script 中的 html 标签?

arrays - 在 Apps 脚本中从数组创建新数组并将值推送到不同工作表的最佳方法是什么?