var oDocument = Api.GetDocument() // As new elements appear when filling tables and lists, the total number of elements in the document increases, // so we need to store references to elements, or increase the loop counter when traversing document elements. var oDocumentElementsCount = oDocument.GetElementsCount() var oDocumentElements = [] for (var i = 0; i < oDocumentElementsCount; i++) { var oElement = oDocument.GetElement(i) oDocumentElements.push(oElement) } oDocumentElements.forEach((oElement) => { fillElementByType(oElement) }) // From docs: // 💡 Please note that the current paragraph must be in the document (not in the footer/header). // And if the current paragraph is placed in a shape, then a caption is added after (or before) the parent shape. // So, numbering in shapes and footer/header is not supported. // fill header and footer var oSection = oDocument.GetFinalSection() var oHeader = oSection.GetHeader("default", true) var oFooter = oSection.GetFooter("default", true) var oHeaderElementsCount = oHeader.GetElementsCount() var oFooterElementsCount = oFooter.GetElementsCount() for (var i = 0; i < oHeaderElementsCount; i++) { var oElement = oHeader.GetElement(i) var oElementClassType = oElement.GetClassType() if (oElementClassType === "paragraph" && oElement.GetNumbering()) { continue } else { fillElementByType(oElement) } } for (var i = 0; i < oFooterElementsCount; i++) { var oElement = oFooter.GetElement(i) var oElementClassType = oElement.GetClassType() if (oElementClassType === "paragraph" && oElement.GetNumbering()) { continue } else { fillElementByType(oElement) } } // fill form in shapes object var oShapes = oDocument.GetAllShapes() oShapes.forEach((oShape) => { var oShapesClassType = oShape.GetClassType() if (oShapesClassType === "shape") { var oShapeContent = oShape.GetDocContent() try { var oShapeContentClassType = oShapeContent.GetClassType() if (oShapeContentClassType === "documentContent") { var oShapeElementsCount = oShapeContent.GetElementsCount() for (var i = 0; i < oShapeElementsCount; i++) { var oElement = oShapeContent.GetElement(i) var oElementClassType = oElement.GetClassType() if (oElementClassType === "paragraph" && oElement.GetNumbering()) { continue } else { fillElementByType(oElement) } } } } catch (_e) {} } }) function getData(keyPath, index = 0, obj = fields) { const keys = keyPath.split(" ") // Recursive function to traverse the object and get the desired value(s) function traverse(obj, keys) { if (keys.length === 0) return obj let key = keys[0] let remainingKeys = keys.slice(1) if (Array.isArray(obj)) { return obj.map((item) => traverse(item, [key, ...remainingKeys])) } else { if (typeof obj[key] === "undefined") { return "" } return traverse(obj[key], remainingKeys) } } // Get the value(s) from the object based on the keys let values = traverse(obj, keys) if (typeof values[index] === "undefined") { return "" } if (Array.isArray(values[0])) { // If the first element is an array, return a concatenated string of all values by key return values[index].flat().join(" ") } else if (Array.isArray(values) && typeof values[index] !== "object") { // If values are an array, return the value at the specified index return values[index] } else { // If the value is not an array, return it as is return values } } function getDataArrayLength(keyPath, obj = fields) { const keys = keyPath.split(" ") let currentObj = obj for (let key of keys) { if (typeof currentObj === "undefined") { return 0 } if (Array.isArray(currentObj)) { return currentObj.length } currentObj = currentObj[key] } return 0 } function fillElementByType(oElement) { var oElementClassType = oElement.GetClassType() if (oElementClassType === "paragraph") { if (oElement.GetNumbering()) { fillNumbering(oElement) } else { fillParagraph(oElement) } } if (oElementClassType === "form" || oElementClassType === "textForm") { fillForm(oElement) } if (oElementClassType === "run") { } if (oElementClassType === "table") { fillTable(oElement) } if (oElementClassType === "pictureForm") { fillForm(oElement) } } function fillParagraph(oParagraph) { var oParagraphElementsCount = oParagraph.GetElementsCount() for (var i = 0; i < oParagraphElementsCount; i++) { var oElement = oParagraph.GetElement(i) fillElementByType(oElement) } } function fillNumbering(oParagraph) { var requiredLevel = 0 var oParagraphElementsCount = oParagraph.GetElementsCount() for (var i = 0; i < oParagraphElementsCount; i++) { var oElement = oParagraph.GetElement(i) var oElementClassType = oElement.GetClassType() if (oElementClassType === "form" || oElementClassType === "textForm" || oElementClassType === "pictureForm") { var oForm = oElement var oFormKey = oForm.GetFormKey() var data = getData(oFormKey, 0) var length = getDataArrayLength(oFormKey) requiredLevel = Math.max(requiredLevel, length) fillForm(oForm, data) } } if (requiredLevel > 1) { var oNumberingLevel = oParagraph.GetNumbering() var oCurrentParagraph = oParagraph for (var newLevel = 1; newLevel < requiredLevel; newLevel++) { var nPos = oCurrentParagraph.GetPosInParent() var oNewParagraph = oParagraph.Copy() oNewParagraph.SetNumbering(oNumberingLevel) var oParagraphElementsCount = oNewParagraph.GetElementsCount() for (var element = 0; element < oParagraphElementsCount; element++) { var oElement = oNewParagraph.GetElement(element) var oElementClassType = oElement.GetClassType() if (oElementClassType === "form" || oElementClassType === "textForm" || oElementClassType === "pictureForm") { var oForm = oElement var oFormKey = oForm.GetFormKey() oForm.SetFormKey(oFormKey + newLevel) var data = getData(oFormKey, newLevel) fillForm(oForm, data) } } oDocument.AddElement(nPos + 1, oNewParagraph) oCurrentParagraph = oNewParagraph } } } function fillTable(oTable) { var rows = oTable.GetRowsCount() for (var row = 0; row < rows; row++) { var oRow = oTable.GetRow(row) var cols = oRow.GetCellsCount() // If there is a form in the cell, then write the length of the array using the form key. // Maximum length - the number of lines that must be inserted after the current row. var requiredRows = 0 var tableData = {} for (var col = 0; col < cols; col++) { var oCell = oTable.GetCell(row, col) var oCellContent = oCell.GetContent() // Enum of paragraphs inside the cell var oCellElementsCount = oCellContent.GetElementsCount() for (var cellElement = 0; cellElement < oCellElementsCount; cellElement++) { var oCellElement = oCellContent.GetElement(cellElement) if (oCellElement.GetClassType() !== "paragraph") { fillElementByType(oCellElement) } else { // Enum paragraph elements inside a cell var oParagraphElementsCount = oCellElement.GetElementsCount() for (var paragraphElement = 0; paragraphElement < oParagraphElementsCount; paragraphElement++) { var oParagraphElement = oCellElement.GetElement(paragraphElement) if ( oParagraphElement.GetClassType() !== "form" && oParagraphElement.GetClassType() !== "textForm" && oParagraphElement.GetClassType() !== "pictureForm" ) { fillElementByType(oParagraphElement) } else { // Fill the first element and count the number of required rows var oForm = oParagraphElement var oFormKey = oForm.GetFormKey() var data = getData(oFormKey, 0) var length = getDataArrayLength(oFormKey) requiredRows = Math.max(requiredRows, length) fillForm(oForm, data) } } } } } if (requiredRows > 1) { // Add new rows, the first row is already there and filled // In each cell of the column we copy the previous cell to save the structure. oTable.AddRows(oTable.GetCell(row, 0), requiredRows - 1, false) for (var newRow = 1; newRow < requiredRows; newRow++) { for (var col = 0; col < cols; col++) { var oNewCell = oTable.GetCell(row + newRow, col) var oCell = oTable.GetCell(row, col) var oCellContent = oCell.GetContent() var oCellElementsCount = oCellContent.GetElementsCount() for (var i = 0; i < oCellElementsCount; i++) { // Get the contents of the cell for further copying to a new cell var oCellElement = oCellContent.GetElement(i) // Copy the contents of a cell to paste into a new cell var oNewCellElement = oCellElement.Copy() // If this is not a paragraph, paste into a new cell unchanged if (oCellElement.GetClassType() !== "paragraph") { oNewCell.AddElement(i, oNewCellElement) } else { // If it is a paragraph, process the elements of the paragraph to fill the forms inside var oParagraphElementsCount = oNewCellElement.GetElementsCount() for (var paragraphElement = 0; paragraphElement < oParagraphElementsCount; paragraphElement++) { var oNewParagraphElement = oNewCellElement.GetElement(paragraphElement) if ( oNewParagraphElement.GetClassType() === "form" || oNewParagraphElement.GetClassType() === "textForm" || oNewParagraphElement.GetClassType() === "pictureForm" ) { var oForm = oNewParagraphElement var oFormKey = oForm.GetFormKey() var data = getData(oFormKey, newRow) fillForm(oForm, data) } } oNewCell.AddElement(i, oNewCellElement) } } // After creating a new cell, there is an empty paragraph inside. Remove it var oNewCellContent = oNewCell.GetContent() var oNewCellElementsCount = oNewCellContent.GetElementsCount() oNewCellContent.RemoveElement(oNewCellElementsCount - 1) } } rows += requiredRows - 1 row += requiredRows - 1 } } } // In odoo, if there is no data in the field, the value will be false function fillForm(oForm, data = null) { var oFormFormType = oForm.GetFormType() if (oFormFormType === "form" || oFormFormType === "textForm") { function fillTextForm(data) { data = String(data) if (data === "false" || data === "undefined") { oForm.SetText(" ") } else { oForm.SetText(data) } } if (data === null) { var oFormKey = oForm.GetFormKey() data = getData(oFormKey) fillTextForm(data) } else { fillTextForm(data) } } if (oFormFormType === "comboBoxForm") { } if (oFormFormType === "dropDownForm") { } if (oFormFormType === "checkBoxForm") { function fillCheckBoxForm(data) { try { data = JSON.parse(data) oForm.SetChecked(data) } catch (_e) { // TODO: set checked BoxForm in case of error } } if (data === null) { var oFormKey = oForm.GetFormKey() var data = getData(oFormKey) fillCheckBoxForm(data) } else { fillCheckBoxForm(data) } } if (oFormFormType === "radioButtonForm") { } if (oFormFormType === "pictureForm") { function fillPictureForm(data) { if (typeof data === "string") { oForm.SetImage(`data:image/png;base64, ${data}`) } } if (data === null) { var oFormKey = oForm.GetFormKey() data = getData(oFormKey) fillPictureForm(data) } else { fillPictureForm(data) } } } Api.Save()