From 81f6b6ae281d33280fb16521bcc6a080377a1aa1 Mon Sep 17 00:00:00 2001 From: Cherrelle Date: Tue, 16 Jan 2024 23:59:01 -0600 Subject: [PATCH] resolve #40 --- actionTrackerSheet.js | 244 +++++++++++++++++++++++++++++++++--------- 1 file changed, 191 insertions(+), 53 deletions(-) diff --git a/actionTrackerSheet.js b/actionTrackerSheet.js index e6ac331..40cb0e3 100644 --- a/actionTrackerSheet.js +++ b/actionTrackerSheet.js @@ -77,6 +77,7 @@ function onOpen() { .addItem('Push actions from MO', 'pushActionsFromTabMO') .addItem('Push actions from SEP', 'pushActionsFromTabSEP') .addItem('Push actions from DevSeed', 'pushActionsFromTabDevSeed') + .addItem('Push actions from AssessmentHQ', 'pushActionsFromTabAssessmentHQ') .addToUi(); } @@ -86,7 +87,7 @@ var folderIds = { MO: '1SRIUs7CUEdGUw0r1PI52e0OJpfXYN0z8', SEP: '1Cw_sdH_IleGbtW1mVoWnJ0yqoyzr4Oe0', DevSeed: '1Bvj1b1u2LGwjW5fStQaLRpZX5pmtjHSj', - AssessmentHQ: '1MEKTRBKum3UA4q97i9FJeBn49tMckbIn'// Assessment HQ Weekly Agenda/Notes + AssessmentHQ: '1V40h1Df4TMuuGzTMiLHxyBRPC-XJhQ10'// Testing Folder }; ///////////////////Pull/////////////////////////////////////////////// @@ -128,6 +129,35 @@ function pullActionsForFolderAssessmentHQ() { }, 'pullActionsForFolderAssessmentHQ'); } +// Helper function to convert .docx file to Google Doc +function convertDocxToGoogleDoc(fileId) { + var file = DriveApp.getFileById(fileId); + var docxBlob = file.getBlob(); + + // Convert .docx to Google Doc + var options = { + method: "POST", + contentType: "application/json", + payload: JSON.stringify({ + title: file.getName(), + mimeType: MimeType.GOOGLE_DOCS + }), + headers: { + Authorization: "Bearer " + ScriptApp.getOAuthToken() + }, + muteHttpExceptions: true + }; + + var response = UrlFetchApp.fetch("https://www.googleapis.com/drive/v2/files/" + fileId + "/copy", options); + var googleDocId = JSON.parse(response.getContentText()).id; + + // Delete the original .docx file + DriveApp.getFileById(fileId).setTrashed(true); + + return googleDocId; +} + + // Helper function to pull actions from a specific folder function pullActionsForFolder(folderName) { var folderId = folderIds[folderName]; @@ -142,47 +172,46 @@ function pullActionsForFolder(folderName) { Logger.log('Step 2: Sheet populated with actions.'); } -// Pull helper function: Pull actions from documents +// Modified pullActionsFromDocuments function function pullActionsFromDocuments(folderId) { var folder = DriveApp.getFolderById(folderId); - var files = folder.getFilesByType(MimeType.GOOGLE_DOCS); + var files = folder.getFiles(); var allActions = []; while (files.hasNext()) { var file = files.next(); - var docId = file.getId(); + var docId; + + if (file.getMimeType() === MimeType.GOOGLE_DOCS) { + docId = file.getId(); + } else if (file.getMimeType() === MimeType.MICROSOFT_WORD || file.getName().toLowerCase().endsWith(".docx")) { + // Convert .docx file to Google Doc + docId = convertDocxToGoogleDoc(file.getId()); + } else { + // Skip unsupported file types + continue; + } + var doc = DocumentApp.openById(docId); var tables = doc.getBody().getTables(); for (var i = 0; i < tables.length; i++) { var table = tables[i]; - var numCols = table.getRow(0).getNumCells(); - - if (numCols !== 3) { // Skip tables that do not have 3 columns - continue; - } - - var documentName = file.getName(); - var documentLink = '=HYPERLINK("' + file.getUrl() + '", "' + documentName + '")'; + var headers = getTableHeaders(table); - if (documentName.toLowerCase().indexOf('template') !== -1) { // Skip files with "Template" in the title - continue; - } - - var tableData = tableTo2DArray(table); - var modifiedTableData = tableData.map(function (row) { - return [documentLink].concat(row); - }); + // Check if the table has the required headers + if (hasRequiredHeaders(headers)) { + var documentName = file.getName(); + var documentLink = '=HYPERLINK("' + file.getUrl() + '", "' + documentName + '")'; - for (var j = 0; j < modifiedTableData.length; j++) { - var row = modifiedTableData[j]; + var tableData = tableTo2DArray(table); + var filteredTableData = filterTableData(tableData, headers); - if (row.some(function (cell) { return cell === ''; })) { // Skip rows with empty cells - continue; + for (var j = 0; j < filteredTableData.length; j++) { + var row = [documentLink].concat(filteredTableData[j]); + allActions.push(row); } - - allActions.push(row); } } } @@ -279,36 +308,45 @@ pullActionsForAllFolders: success 11:02:56 AM pullActionsForAllFolders executi ////////////////// Push //////////////////////////////////////////////////////// -// Function to call the primary function on all named tabs +// Push function to call the primary function on all named tabs function pushActionsFromAllTabs() { logExecutionTime(function() { updateStatusOnTab("MO"); updateStatusOnTab("SEP"); updateStatusOnTab("DevSeed"); + updateStatusOnTab("AssessmentHQ"); }, 'pushActionsFromAllTabs'); } -// Function to call the primary function on the "MO" tab +// Push function to call the primary function on the "MO" tab function pushActionsFromTabMO() { logExecutionTime(function() { updateStatusOnTab("MO"); }, 'pushActionsFromTabMO'); } -// Function to call the primary function on the "SEP" tab +// Push function to call the primary function on the "SEP" tab function pushActionsFromTabSEP() { logExecutionTime(function() { updateStatusOnTab("SEP"); }, 'pushActionsFromTabSEP'); } -// Function to call the primary function on the "DevSeed" tab +// Push function to call the primary function on the "DevSeed" tab function pushActionsFromTabDevSeed() { logExecutionTime(function() { updateStatusOnTab("DevSeed"); }, 'pushActionsFromTabDevSeed'); } +// Push function to call the primary function on the "AssessmentHQ" tab +function pushActionsFromTabAssessmentHQ() { + logExecutionTime(function() { + updateStatusOnTab("AssessmentHQ"); + }, 'pushActionsFromTabAssessmentHQ'); +} + +// push function: function updateStatusOnTab(tabName) { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(tabName); var range = sheet.getRange("A:G"); // Assuming the URL is in Column G @@ -332,6 +370,7 @@ function updateStatusOnTab(tabName) { } } +//push function: function updateStatusInSourceDoc(actionSource, status, task) { // Column G now contains the extracted URL var actionSourceUrl = actionSource; // No need for extractUrlFromHyperlink @@ -341,51 +380,149 @@ function updateStatusInSourceDoc(actionSource, status, task) { return; } - try { - console.log("Attempting to open document with URL:", actionSourceUrl); - var sourceDoc = DocumentApp.openByUrl(actionSourceUrl); - } catch (error) { - console.error("Error opening document by URL:", error); - return; - } + try { + console.log("Attempting to open document with URL:", actionSourceUrl); + var sourceDoc = DocumentApp.openByUrl(actionSourceUrl); + } catch (error) { + console.error("Error opening document by URL:", error); + return; + } + // Get the body of the document var body = sourceDoc.getBody(); // Find the table with the specified headings - var table = findTableByHeadings(body, ["Status", "Action"]); + var table = findTableByHeadings(body); if (table) { - // Find the row with the matching task in the "Action" column - var rowIndex = findRowIndexByColumnValue(table, "Action", task); + // Log the table content for investigation + console.log("Table Content:", table.getText()); + + // Check the headers dynamically and find the row with the matching task + var columnIndex; + var expectedHeaders; + var lowerCaseHeaders = table.getRow(0).getText().toLowerCase().trim(); // Trim leading/trailing spaces + if (lowerCaseHeaders.includes("who")) { + // Headers are "Who What Status" + columnIndex = getColumnIndex(table, "What"); + expectedHeaders = "Who What Status"; + } else if (lowerCaseHeaders.includes("status") && + lowerCaseHeaders.includes("owner") && + lowerCaseHeaders.includes("action")) { + // Headers are "Status Owner Action" + columnIndex = getColumnIndex(table, "Action"); + expectedHeaders = "Status Owner Action"; + } else { + // Headers not recognized + console.error("Headers not recognized. Detected headers:", lowerCaseHeaders); + expectedHeaders = "Unknown"; + } + + // Find the row with the matching task in the specified column + var rowIndex = findRowIndexByColumnValue(table, table.getRow(0).getCell(columnIndex).getText(), task); if (rowIndex !== -1) { // Update the "Status" column with the status from the sheet table.getCell(rowIndex, getColumnIndex(table, "Status")).setText(status); + console.log("Status Updated Successfully!"); + } else { + console.error("Row with task not found in the table. Expected headers:", expectedHeaders); } + } else { + console.error("Table not found with specified headings. Expected headers:", expectedHeaders); + } +} + +// Push function: Get table headers +function getTableHeaders(table) { + var headers = []; + var row1 = table.getRow(0); + + for (var col = 0; col < row1.getNumCells(); col++) { + headers.push(row1.getCell(col).getText().trim()); + } + + return headers; +} + +// Helper function: Check if the table has the required headers +function hasRequiredHeaders(headers) { + // Check if the table has "Status" "Owner" "Action" or "Who" "What" "Status" + var hasStatus = headers.includes('Status') || headers.includes('Who'); // Column one heading + var hasOwner = headers.includes('Owner') || headers.includes('What'); // Column two heading + var hasAction = headers.includes('Action') || headers.includes('Status'); // Column three heading + + return hasStatus && hasOwner && hasAction; +} + +// Helper function: Filter table data based on headers +function filterTableData(tableData, headers) { + var filteredData = []; + + for (var i = 0; i < tableData.length; i++) { + var rowData = tableData[i]; + var filteredRow = ['', '', '']; // Initialize with empty values + + for (var j = 0; j < headers.length; j++) { + var header = headers[j]; + var columnIndex = headers.indexOf(header); + + if (columnIndex !== -1) { + // Set values in corresponding columns based on header variations + switch (header.toLowerCase()) { + case 'status owner action': + filteredRow[0] = rowData[columnIndex]; + filteredRow[1] = rowData[columnIndex + 1]; // Assuming 'Owner' is next + filteredRow[2] = rowData[columnIndex + 2]; // Assuming 'Action' is next + break; + case 'who what status': + filteredRow[0] = rowData[columnIndex + 2]; // Assuming 'Status' is last + filteredRow[1] = rowData[columnIndex]; // Assuming 'Who' is first + filteredRow[2] = rowData[columnIndex + 1]; // Assuming 'What' is in the middle + break; + // Add more cases for other header variations if needed + } + } + } + + filteredData.push(filteredRow); } + return filteredData; } -function findTableByHeadings(body, headings) { - // Function to find a table in the document with specified headings +function findTableByHeadings(body) { + // Push function to find a table in the document with specified headings var tables = body.getTables(); - + + // Define possible header patterns + var headerPatterns = [ + ["who", "what", "status"], + ["status", "owner", "action"] + ]; + for (var i = 0; i < tables.length; i++) { var table = tables[i]; var headerRow = table.getRow(0); - - // Check if the table has the specified headings - if (headings.every(function (heading) { - return headerRow.getText().indexOf(heading) !== -1; - })) { - return table; + var headerText = headerRow.getText().toLowerCase().replace(/\n/g, ''); + + // Check if the table headers match any of the predefined patterns + for (var j = 0; j < headerPatterns.length; j++) { + var pattern = headerPatterns[j]; + var patternText = pattern.join(""); + if (headerText.includes(patternText)) { + console.log("Table found with specified headings:", patternText); + return table; + } } } - + + console.error("Table not found with specified headings."); + console.log("Detected headings:", tables.map(table => table.getRow(0).getText().toLowerCase())); return null; } function findRowIndexByColumnValue(table, columnName, value) { - // Function to find the row index in the table with a specific column value + // Push function to find the row index in the table with a specific column value var columnIndex = getColumnIndex(table, columnName); if (columnIndex !== -1) { @@ -402,7 +539,7 @@ function findRowIndexByColumnValue(table, columnName, value) { } function getColumnIndex(table, columnName) { - // Function to get the index of a column in the table + // Push function to get the index of a column in the table var headerRow = table.getRow(0); var numCells = headerRow.getNumCells(); @@ -421,7 +558,8 @@ function getColumnIndex(table, columnName) { 'pushActionsFromTabMO': success 3:59:02 PM execution time: 0 minutes, 13.421 seconds 'pushActionsFromTabSEP': success 4:02:31 PM execution time: 0 minutes, 15.707 seconds 'pushActionsFromTabDevSeed': success 4:12:57 PM execution time: 0 minutes, 11.042 seconds -'pushActionsFromAllTabs': 4:16:43 PM execution time: 0 minutes, 31.064 seconds +'pushActionsFromAssessmentHQ': success 11:55:32 PM execution time: 0 minutes, 4.876 seconds +'pushActionsFromAllTabs': success 11:57:00 PM execution time: 0 minutes, 35.094 seconds */ ///////////////Combine Open Actions///////////////////////////////////////////////