how would you set up to trigger generation and display of a QR code using the following process:
THE FOLLOWING PORTION OF THE PROCESS IS BUILT AND SUCCESSFULLY PERFORMING URL SHORTEN AND CUSTOMIZATION AND POPULATING SHORT URL IN SPREADSHEET.
CONTEXT
[ in summary i need the QR code image to be viewable and scannable in the detail view post creation of the bitly short URL. ]
THIS IS WHERE I HIT A ROADBLOCK.
ive tried so many different App Scripts and tried to query Gen AI and have read and re-read all bitlys QR generation documentation and i guess im just not seeing something but i can't seem to figure out how to
THIS LAST PART IS A MAJOR FEATURE DEPENDENCY.
Essentially once a piece of equipment is added to the inventory an employee will be required to scan the Qr Code listed in the equipments detail view and check it out to enforce equipment tracking and accountability .
below is my app script functions. i have it split to accommodate specific steps of the process so it ensures the dependent data is populated before proceeding to the next step. Also i have helper functions not directly called from appsheet but generate dependent constructors used in the functions themselves.
ShortURL
const properties = PropertiesService.getScriptProperties().getProperties();
const apiKey = properties['API_KEY'];
const domain = properties['DOMAIN'];
const group = properties['GROUP_GUID'];
const baseUrl = properties['BASE_URL']
const drive = properties['FOLDER_ID']
function shortenURL(longUrl) {
const apiEndpoint = `https://api-ssl.bitly.com/v4/shorten`;
const options = {
'method': 'POST',
'headers': {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
},
'payload': JSON.stringify({
'long_url': longUrl,
'domain': domain,
'group_guid': group
})
};
const response = UrlFetchApp.fetch(apiEndpoint, options);
const data = JSON.parse(response.getContentText());
// Log the short link and QR code link
Logger.log('Short Link: ' + data.link);
return {
shortLink: data.link
};
}
Helper functions
GET QR ID from generated short link
function getQRID(shortLink) {
const url = `https://api-ssl.bitly.com/v4/bitlinks/` + shortLink;
const headers = {
'Authorization': apiKey,
};
const response = UrlFetchApp.fetch(url, { headers: headers });
if (response.getResponseCode() === 200) {
const data = JSON.parse(response.getContentText());
return data.id;
} else {
throw new Error("Error retrieving shortlink data");
}
}
Get the bitly qr code image link created in parallel with the shortLink by Bitly
function getQRImg(shortLink) {
const qrCodeId = getQRID(shortLink);
const url = `https://api-ssl.bitly.com/v4/bitlinks/` + qrCodeId + `/qr`;
const headers = {
'Authorization': apiKey,
'Content-Type': 'application/json' // Set content type for JSON payload
};
// Create payload object with the QR code URL
const payload = {
qr_code: qrCodeId
};
const options = {
'method': 'post',
'headers': headers,
'payload': JSON.stringify(payload)
};
const response = UrlFetchApp.fetch(url, options);
if (response.getResponseCode() === 200) {
const data = JSON.parse(response.getContentText());
const qrCodeUrl = data.qr_code;
Logger.log("QR Image URL:", qrCodeUrl);
Logger.log("Full QR Code Data:", data);
// Fetch QR image data
const imgResponse = UrlFetchApp.fetch(qrCodeUrl);
// **Log for Debugging:**
Logger.log("QR Image Response Code:", imgResponse.getResponseCode());
Logger.log("QR Image URL:", qrCodeUrl);
if (imgResponse.getResponseCode() !== 200) {
throw new Error(`Error fetching QR image: ${imgResponse.getContentText()}`);
}
const blob = imgResponse.getBlob();
return blob;
} else {
throw new Error("Error fetching QR image");
}
}
Upload Qr code image to google drive and add drive link to QRLink column in spreadsheet and viewable by referencing url in the QRImg column of the same row
function generateAndSaveQR(shortLink) {
try {
// 1. Create the QR Code and get the QR code ID
const qrCodeId = getQRID(shortLink);
// 2. Fetch the QR code image
const blob = getQRImg(shortLink);
// 3. Save to Google Drive
const folder = DriveApp.getFolderById(driveFolderId);
const fileName = `${shortLink}.png`;
const file = folder.createFile(fileName, blob);
Logger.log("QR Code Image saved to Google Drive:", file.getUrl());
return {
filePath: file.getUrl(), // Return the full file path
fileName: file.getName()
};
} catch (error) {
Logger.log(`Error generating QR code and image: ${error.message}`);
return null;
}
}
the entire automation on Appsheets triggers, as well as app script returning bitly short link to spreadsheet working great but there is a disconnect when trying to get the actual qr image that populates with the bitly shorlink to upload an image file to drive and return the drive file link back into the associated row.
And all the logging and debugging messages when the automation runs will provide is the following error message:
"Error generating QR code and image: Error fetching QR image"
Solved! Go to Solution.
Is there some requirement that you have to use bitly for the QR code? Plenty of other QR generation options out there that can accomplish this far easier. As in you simply concatenate together a URL to the QR api and store that URL value in an Image column.
Thank you so much for helping me with this. I was overthinking it.
Corrected Workflow:
3 columns used
[LongURL]
// uses CONCATENATE & LINKTOROW to capture the detail view URL when the "Add Equipment To Inventory" form is saved and is passed as a variable to app script.
This is the expression i used
IF(
[Class]='Team',
TEXT( HYPERLINK( CONCATENATE(
'https://www.appsheet.com/start/******#appName=${Your AppName}&table=${QR Detail
View}&row=', LINKTOROW([ID], "<<TableToLinkQRCodeTo>>_Detail","YourAppName")),
"")),
ISBLANK([_THIS])
)
This is the app script function with longUrl variable
const properties = PropertiesService.getScriptProperties().getProperties();
const apiKey = properties['API_KEY'];
const domain = properties['DOMAIN'];
const group = properties['GROUP_GUID'];
const baseUrl = properties['BASE_URL']
function shortenURL(longUrl) {
const apiEndpoint = `https://api-ssl.bitly.com/v4/shorten`;
const options = {
'method': 'POST',
'headers': {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
},
'payload': JSON.stringify({
'long_url': longUrl,
'domain': domain,
'group_guid': group
})
};
const response = UrlFetchApp.fetch(apiEndpoint, options);
const data = JSON.parse(response.getContentText());
// Log the short link and QR code link
Logger.log('Short Link: ' + data.link);
return {
shortLink: data.link
};
}
[ShortURL]
// Placeholder for the return object from my bitly automation that contains the formatted the LongURL
[QRUrl]
// this concatenates my ShortURL into the QR request link and is triggered when the ShortURL before value <> the ShortURL after value and only works with adds.
This is the expression I used
HYPERLINK(
CONCATENATE(
"https://qrcode.tec-it.com/API/QRCode?data=",
[_THISROW].[ShortURL],
"&backcolor=%23ffffff"
), ""
)โ
[QR]
// this is the image column used to display the QR in the details view so users can scan the equipment QR to check out the equipment or find info on them. there are also QR stickers on the equipment so techs can just scan with the app and be directed to the detail view in the app.
This is the expression i used:
ENCODEURL( [_THISROW].[QRUrl] )โ
Good work.
I'm not sure your full requirements, but perhaps you can simplify it even further. Are you needing the shortened bitly link for something else? If not, the qr api certainly does need it, it can generate a qr code from the full length url. You also don't need the intermediate qr-url column, you can just concatenate it directly in the qr-image column. You definitely don't need any of the [_THISROW].'s that you used, and oftentimes using them when it's not necessary can cause weird issues, so you shouldn't do it. You also probably don't need that encodeurl().
Is there some requirement that you have to use bitly for the QR code? Plenty of other QR generation options out there that can accomplish this far easier. As in you simply concatenate together a URL to the QR api and store that URL value in an Image column.
Thank you so much for helping me with this. I was overthinking it.
Corrected Workflow:
3 columns used
[LongURL]
// uses CONCATENATE & LINKTOROW to capture the detail view URL when the "Add Equipment To Inventory" form is saved and is passed as a variable to app script.
This is the expression i used
IF(
[Class]='Team',
TEXT( HYPERLINK( CONCATENATE(
'https://www.appsheet.com/start/******#appName=${Your AppName}&table=${QR Detail
View}&row=', LINKTOROW([ID], "<<TableToLinkQRCodeTo>>_Detail","YourAppName")),
"")),
ISBLANK([_THIS])
)
This is the app script function with longUrl variable
const properties = PropertiesService.getScriptProperties().getProperties();
const apiKey = properties['API_KEY'];
const domain = properties['DOMAIN'];
const group = properties['GROUP_GUID'];
const baseUrl = properties['BASE_URL']
function shortenURL(longUrl) {
const apiEndpoint = `https://api-ssl.bitly.com/v4/shorten`;
const options = {
'method': 'POST',
'headers': {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
},
'payload': JSON.stringify({
'long_url': longUrl,
'domain': domain,
'group_guid': group
})
};
const response = UrlFetchApp.fetch(apiEndpoint, options);
const data = JSON.parse(response.getContentText());
// Log the short link and QR code link
Logger.log('Short Link: ' + data.link);
return {
shortLink: data.link
};
}
[ShortURL]
// Placeholder for the return object from my bitly automation that contains the formatted the LongURL
[QRUrl]
// this concatenates my ShortURL into the QR request link and is triggered when the ShortURL before value <> the ShortURL after value and only works with adds.
This is the expression I used
HYPERLINK(
CONCATENATE(
"https://qrcode.tec-it.com/API/QRCode?data=",
[_THISROW].[ShortURL],
"&backcolor=%23ffffff"
), ""
)โ
[QR]
// this is the image column used to display the QR in the details view so users can scan the equipment QR to check out the equipment or find info on them. there are also QR stickers on the equipment so techs can just scan with the app and be directed to the detail view in the app.
This is the expression i used:
ENCODEURL( [_THISROW].[QRUrl] )โ
Good work.
I'm not sure your full requirements, but perhaps you can simplify it even further. Are you needing the shortened bitly link for something else? If not, the qr api certainly does need it, it can generate a qr code from the full length url. You also don't need the intermediate qr-url column, you can just concatenate it directly in the qr-image column. You definitely don't need any of the [_THISROW].'s that you used, and oftentimes using them when it's not necessary can cause weird issues, so you shouldn't do it. You also probably don't need that encodeurl().
User | Count |
---|---|
18 | |
15 | |
10 | |
7 | |
4 |