0

I have a Google Sheet spreadsheet containing personal data I collect from people who subscribe to my association. They have to complete an online form and sign it. The data is then sent to the spreadsheet and the signature is imported as a PNG in-cell-image.

I need to extract all the PNG signatures and assign them the specific ID found in the same row so I can later match the signature with the correct personal data when generating a PDF form with another script.

ID Signature
1a2b3c4d image.png
5e6f7g7h image.png

I am currently using the following code I found online. It saves all the images to a folder as PNG files but it assigns names like "image-1", "image-2" in a random order.

Here is the code:

function myFunction() {
  const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
  const url = "https://docs.google.com/spreadsheets/export?exportFormat=xlsx&id=" + spreadsheetId;
  const blob = UrlFetchApp.fetch(url, {headers: {authorization: `Bearer ${ScriptApp.getOAuthToken()}`}}).getBlob().setContentType(MimeType.ZIP);
  const xlsx = Utilities.unzip(blob);
  xlsx.forEach(b => {
    const name = b.getName().match(/xl\/media\/(.+)/);
    if (name) DriveApp.getFolderById("1mdJbbG_0aF8wjEIuVPsMr9jV31wPINRk").createFile(b.setName(name[1]));
  });
}

How can I edit the code to name each file with the corresponding ID?

Thanks a lot!

EDIT:

I collect data from an online form which is displayed in the image below.

Online Form

When clicking on the signature field, a signature pad opens and allows the user to sign.

Signature Pad

Collected data are then sent to the following spreadsheet stored in Google Drive.

Spreadsheet

The script which sends data from the form to the spreadsheet should be the following

function submit(data) {
  data = JSON.parse(data)
  const headers = SETTINGS.HEADERS.map(({value}) => value)
  const id = Utilities.getUuid()
  const signatures = []
  const values = SETTINGS.HEADERS.map(({key}, index) => {
    if (key === "id") return id
    if (key === "timestamp") return new Date()
    if (!key in data) return null
    if (Array.isArray(data[key])) return data[key].join(",")
    if (data[key].startsWith("data:image")) {
      signatures.push(index)
      return SpreadsheetApp.newCellImage().setSourceUrl(data[key]).build().toBuilder()
    }
    return data[key]

  })
  const ws = SpreadsheetApp.getActive().getSheetByName(SETTINGS.SHEET_NAME.RESPONSES) || SpreadsheetApp.getActive().insertSheet(SETTINGS.SHEET_NAME.RESPONSES)
  ws.getRange(1,1, 1, headers.length).setValues([headers])
  const lastRow = ws.getLastRow()
  ws.getRange(lastRow + 1, 1, 1, values.length).setValues([values])
  signatures.forEach(index => {
    ws.getRange(lastRow + 1, index + 1).setValue(values[index])
  })
  return JSON.stringify({success: true, message: `Grazie per la tua richiesta di iscrizione! ID: ${id}`})

}

The need is to rename the signature image with the submission ID.

In that way, in theory, when I run Tanaike's script to extract the images from the spreadsheet, they should be named with the ID of the corresponding form submission.

As of now, when I run Tanaike's script I get the following output.

Tanaike's script output

Thanks a lot!

alecanc
  • 29
  • 5
  • First, if your showing script was [my script in this thread](https://stackoverflow.com/a/64040243), I apologize that my sample script was not useful for your situation. I have a question. In your situation, `image.png` of `Signature` is the inserted image in a cell? If my understanding is correct, how is the image inserted? – Tanaike Oct 14 '22 at 00:04
  • Thanks a lot @Tankie for providing the script I used. It is indeed the script you posted in that thread. I will add a reply below to show my issue in more detail by adding a few images. – alecanc Oct 17 '22 at 09:01
  • Dear @Tanaike the issue is not solved yet. Please check, if you can, my reply below. Thank you! – alecanc Oct 17 '22 at 12:46
  • Thank you for replying. About `the issue is not solved yet.`, I have to apologize for my poor English skill. You had posted an answer. I thought that your issue was resolved. I apologize for this. When your posted answer was not your answer, please delete it and please add it to your question. – Tanaike Oct 17 '22 at 13:02
  • @Tanaike sorry for posting a new answer. I just deleted the new answer and edited the original question. You may find new info under "EDIT:" – alecanc Oct 17 '22 at 13:08
  • Thank you for replying. From your reply and updating the question, I proposed an answer. Could you please confirm it? If that was not useful, I apologize. – Tanaike Oct 17 '22 at 13:37
  • Dear @Tanaike the answer was correct and I was able to name every image with the specific ID. Now I have another issue. I updated my question. Are you able to help me? Thanks a lot for the help provided so far! – alecanc Oct 17 '22 at 14:13
  • Thank you for replying. I'm glad your issue was resolved. About your new question, I would like to support you. But, that is different from your question. So can you post it as new question? Because when your initial question is changed by comment, other users who see your question are confused. By posting it as new question, users including me can think of it. If you can cooperate to resolve your new issue, I'm glad. Can you cooperate to resolve your new question? – Tanaike Oct 17 '22 at 23:39
  • Sorry @Tanaike for my poor understanding of the forum rules. I will open a new thread now and change the title back to its original. – alecanc Oct 18 '22 at 07:31

1 Answers1

0

I believe your goal is as follows.

  • You want to export the images of column "O" in Google Spreadsheet. In this case, you want to use the values of column "B" as the filename.
  • The image is put into the cells as CellImage.

Modification points:

  • Using XLSX data converted from Spreadsheet, when the image files are directly retrieved from XLSX data, unfortunately, the images cannot correspond to each cell coordinate. I thought that this is the reason of your issue. In this case, it is required to parse the XLSX data. But, I thought that in this case, the script might be a bit complicated. So, in order to retrieve the image data from the XLSX with the cell coordinate, I have created a Google Apps Script library. Ref

In this answer, I would like to propose a sample script using the library.

Usage:

1. Install Google Apps Script library.

Please install DocsServiceApp Google Apps Script library. You can see how to install it at here.

2. Sample script.

Please copy and paste the following script to the script editor of Spreadsheet. And, please set the variables of folderId and sheetName.

function myFunction() {
  const folderId = "###"; // Please set folder ID you want to put the created files.
  const sheetName = "Sheet1"; // Please set your sheet name.

  // Retrieve image data.
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const res = DocsServiceApp.openBySpreadsheetId(ss.getId()).getSheetByName(sheetName).getImages();

  // Retrieve IDs from from column "B"
  const folder = DriveApp.getFolderById(folderId);
  const sheet = ss.getSheetByName(sheetName);
  const values = sheet.getRange("B1:B" + sheet.getLastRow()).getValues();
  
  // Create files.
  res.forEach(({ range, image }) =>
    folder.createFile(image.blob.setName(`${values[range.row - 1][0]}.png` || image.blob.getName()))
  );
}
  • When this script is run, the image data is retrieved and created as the image file using the filename retrieved from column "B".

Note:

  • In this sample script, from your provided sample image, it supposes that the image data and the filename are put in the columns "O" and "B", respectively. Please be careful about this.

Reference:

Tanaike
  • 181,128
  • 11
  • 97
  • 165