Blog
2025-10-17 18:35

Deluge: from Quote in Zoho CRM → preview in Sheets → file in WorkDrive → attachment in CRM

The script takes a Quote from Zoho CRM, collects the items, extends preview files by fileId, uploads them to WorkDrive using streaming upload, generates rows in Sheet2 of Zoho Sheets (with previews via the formula =IMAGE()), copies the workbook into the target folder WorkDrive under the Quote’s name, attaches the workbook link to the Quote record in CRM, and finally clears the range in the working sheet for the next generation cycle.

Loading Quote data from CRM

Preparing table headers (for future rows in Sheets)

  • A list row_data and a map header are created with the following columns: “Product Name”, “Description”, “Quantity” and “Price”.
  • The header is appended to row_data.
  • (Note: the same variable name header is later reused for HTTP headers — a potential source of confusion, see “Remarks” below.)

Iterating through Quote Items (Quoted_Items)

For each item, the script extracts:

Product_Name.name, SKU, color, packaging, model/fabric, sizes, print types, quantity, price, total, link, parent ID, and Preview attachments.

Receiving and publishing files preview


Creating a row for Zoho Sheets (Sheet2)

  • A preview formula is built for the cell: =IMAGE("https://previewengine-accl.zoho.eu/image/WD/{resource_id}";1)
  • (Note the semicolon; this is the regional setting for the European argument separator.)
  • The row is compiled with product details, print attributes, links, project data, and dates, then sent via: zoho.sheet.createRecords(resourceId,"Sheet2", rowsData, ...)
  • This process is built for all Quote line items.

Copying the workbook and renaming it after the Quote

  • Call POST https://sheet.zoho.eu/api/v2/copy with parameters:
  • resource_id: source template workbook
  • workbook_name: Quote Subject
  • parent_id: target WorkDrive folder
  • copy_lock_settings: true
  • The workbook_url of the copied workbook is taken from the response.

Attaching the workbook link to the Quote in CRM

  • A request is made to POST https://www.zohoapis.eu/crm/v7/Quotes/{QuoteID}/Attachments with attachmentUrl = workbook_url
  • title = Subject

If DUPLICATE_DATA is received, the script returns a system message; otherwise, it returns Files Generated.
Clearing the working range in Sheet2

  • Finally POST https://sheet.zoho.eu/api/v2/{resourceId}
  • with method range.content.clear and range A2:Q50.
  • This resets the working area for the next run, ensuring old data doesn’t accumulate.
info QuoteID;
// Get Quote data from Zoho CRM
Quote = invokeurl
[
	url :"https://www.zohoapis.eu/crm/v8/Quotes/" + QuoteID
	type :GET
	connection:"crm_zoho_dev"
];
Quote = Quote.get("data").toMap();
//
// Table 
Quote = invokeurl
[
	url :"https://www.zohoapis.eu/crm/v8/Quotes/" + QuoteID
	type :GET
	connection:"crm_zoho_dev"
];
Quote = Quote.get("data").toMap();
Subject = Quote.get("Subject");
Account_Name = Quote.get("Account_Name");
if(Account_Name.isNull() == false)
{
	Account_Name = Account_Name.get("name");
}
Contact_Name = Quote.get("Contact_Name");
if(Contact_Name.isNull() == false)
{
	Contact_Name = Contact_Name.get("name");
}
Owner = Quote.get("Owner").get("name");
Delivery_address = Quote.get("Delivery_address");
Ready_by_date = Quote.get("Ready_by_date");
Sub_Total = Quote.get("Sub_Total");
Valid_Till = Quote.get("Valid_Till");
Grand_Total = Quote.get("Grand_Total");
Tax = Quote.get("Tax");
Adjustment = Quote.get("Adjustment");
currency_symbol = Quote.get("$currency_symbol");
Quoted_Items = Quote.get("Quoted_Items");
info Quoted_Items;
row_data = list();
// Creating a list of lines
// Headings for the table
header = Map();
header.put("Product Name","Product Name");
header.put("Description","Description");
header.put("Quantity","Quantity");
header.put("Price","Price");
row_data.add(header);
// Filling in the data
resourceId = "m78m951ed261da6564fe898b2892823e9af51";
GrandTotal = 0;
for each  rec in Quoted_Items
{
	Product_Name = rec.get("Product_Name").get("name");
	Article = rec.get("Article");
	Color = rec.get("Color");
	Packaging = rec.get("Packaging");
	Fabric_model = rec.get("Fabric_model");
	Print_size = rec.get("Print_size");
	Product_size = rec.get("Product_size");
	Print_type = rec.get("Print_type");
	Quantity = rec.get("Quantity");
	List_Price = rec.get("List_Price");
	Total = rec.get("Total");
	Link = rec.get("Link");
	Parent_Id = rec.get("id");
	Preview = rec.get("Preview");
	for each  rec in Preview
	{
		fileId = rec.get("File_Id__s");
		info "fileId: " + fileId;
		File_Name__s = rec.get("File_Name__s");
		if(rec.get("File_Id__s") != null)
		{
			// Uploading the file by FileID
			fileDownloadUrl = "https://www.zohoapis.eu/crm/v8/files?id=" + fileId;
			// Making a GET request
			file = invokeurl
			[
				url :fileDownloadUrl
				type :GET
				connection:"crm_zoho_dev"
			];
			info file;
			file.setParamName("file");
			//
			header.put("x-filename",File_Name__s);
			header.put("x-parent_id","m78m95115e88cd68f4978895817486547edf4");
			header.put("upload-id",fileId);
			header.put("x-streammode","1");
			response = invokeurl
			[
				url :"https://upload.zoho.eu/workdrive-api/v1/stream/upload"
				type :POST
				parameters:file
				headers:header
				connection:"workdrive"
				content-type:"application/octet-stream"
			];
			info response;
			//
			resource_id = response.get("data").get(0).get("attributes").get("resource_id");
			info resource_id;
			Preview = "https://previewengine-accl.zoho.eu/image/WD/" + resource_id;
			//
		}
	}
	// 	Preview = "https://crmsandbox.zoho.eu/crm/devzn/specific/ViewAttachment?fileId=" + fileId + "&module=QuotedItems&fieldId=625426000000542577&parentId=" + Parent_Id + "&name=" + file + "&downLoadMode=default";
	Preview = "=IMAGE(\"" + Preview + "\";1)";
	info Preview;
	//
	row = Map();
	row.put("Product Name",Product_Name);
	row.put("Preview",Preview);
	row.put("Q",Quantity);
	row.put("Item Price",List_Price);
	row.put("Total Price",Total);
	row.put("Link",Link);
	row.put("Article",Article);
	row.put("Color",Color);
	row.put("Fabric / model",Fabric_model);
	row.put("Packaging",Packaging);
	row.put("Product Size",Print_size);
	row.put("Print Type",Print_type);
	row.put("Print Size",Print_size);
	row.put("Project name",Account_Name);
	row.put("Account manager",Owner);
	row.put("Delivery info",Delivery_address);
	row.put("Ready by date",Ready_by_date);
	rowsData = List();
	rowsData.add(row);
	queryData = Map();
	response = zoho.sheet.createRecords(resourceId,"Sheet2",rowsData,queryData,"zoho_sheet");
	// 		info response;
}
//
paramMap = Map();
paramMap.put('method','workbook.copy');
paramMap.put('resource_id',resourceId);
paramMap.put('workbook_name',Subject);
paramMap.put('parent_id','hmb7xd57420ae63934e46991c703d67eae9de');
paramMap.put('copy_lock_settings','true');
response = invokeurl
[
	url :"https://sheet.zoho.eu/api/v2/copy"
	type :POST
	parameters:paramMap
	connection:"zoho_sheet"
];
info response;
workbook_url = response.get("workbook_url");
info workbook_url;
//
formData = Map();
formData.put("attachmentUrl",workbook_url);
formData.put("title",Subject);
response = invokeurl
[
	url :"https://www.zohoapis.eu/crm/v7/Quotes/" + QuoteID + "/Attachments"
	type :POST
	parameters:formData
	connection:"crm_zoho_dev"
];
info response;
//
if(response.get("code").contains("DUPLICATE_DATA") == true)
{
	result = response.get("message");
}
else
{
	result = "Files Generated";
}
//
paramMap = Map();
paramMap.put('method','range.content.clear');
paramMap.put('worksheet_name','sheet2');
paramMap.put('start_row',2);
paramMap.put('start_column',1);
paramMap.put('end_row',50);
paramMap.put('end_column',17);
response = invokeurl
[
	url :"https://sheet.zoho.eu/api/v2/" + resourceId
	type :POST
	parameters:paramMap
	connection:"zoho_sheet"
];
info response;

Key Variables / Identifiers

  • resourceId — ID of the template Zoho Sheet workbook from which a copy is made.
  • x-parent_id — the WorkDrive folder where preview files are uploaded (and where the workbook copy is also stored).
  • parent_id (in copy) — the destination folder for the copied workbook (may match or differ from x-parent_id).
  • workbook_url — the link to the copied workbook (attached to the Quote in CRM).
  • QuoteID — the target Quotes record in Zoho CRM.

Why do this (practical effect)

  • Visualized Quotes: each line item receives a live preview directly inside Zoho Sheets — convenient for sharing with clients or colleagues.
  • Single artifact: the resulting workbook with all rows and images is automatically attached to the corresponding Quote record in CRM.
  • Auto-cleanup: subsequent generations don’t clutter the template — the defined range is cleared automatically after each run.