From ffdb9cd2b51df500b7768cd0ddfc0f631f6ed15b Mon Sep 17 00:00:00 2001 From: Connor Ivy Date: Fri, 5 May 2023 11:16:45 -0500 Subject: [PATCH] deleting table cleans up metadata --- src/plugins/dataTable.js | 91 ++++++++++++++++++++++++++++++++++++++-- src/plugins/excel.js | 46 +++++++++++++++----- 2 files changed, 123 insertions(+), 14 deletions(-) diff --git a/src/plugins/dataTable.js b/src/plugins/dataTable.js index d00a0f5..7f25b08 100644 --- a/src/plugins/dataTable.js +++ b/src/plugins/dataTable.js @@ -1,5 +1,5 @@ // eslint-disable-next-line no-unused-vars -import { bakeTable, bakeArray, hideRowOrColumn, getIndiciesFromRangeAddress, send } from './excel' +import { bakeTable, bakeArray, hideRowOrColumn, removeNonAlphanumericCharacters } from './excel' export const tableName = 'SpeckleDataTable' export function checkIfReceivingDataTable(item) { @@ -63,7 +63,7 @@ export async function bakeDataTable(item, arrayData, context, sheet, rowStart, c // set table applicationId in the top left cell arrayData[0][0] = `{"SpeckleTableApplicationId":"${item.applicationId}"}` - await bakeTable(arrayData, context, sheet, name, rowStart + headerRowIndex, colStart) + await bakeTable(arrayData, context, sheet, name, rowStart, colStart, headerRowIndex) greyOutReadOnlyColumns( item.columnMetadata, rowStart + 1 + headerRowIndex, @@ -195,7 +195,11 @@ export async function GetColumnMetadataRowIndex(table, sheet, context) { tableRange.columnCount ) - var found = possibleMetadataRowRange.findOrNullObject('SpeckleColumnMetadataRow', { + return await findMetadataRowIndex(possibleMetadataRowRange, context) +} + +async function findMetadataRowIndex(range, context) { + var found = range.findOrNullObject('SpeckleColumnMetadataRow', { completeMatch: false, // Match the whole cell value. matchCase: true, // Don't match case. searchDirection: window.Excel.SearchDirection.forward // Start search at the beginning of the range. @@ -203,7 +207,7 @@ export async function GetColumnMetadataRowIndex(table, sheet, context) { found.load('rowIndex') await context.sync() if (found.isNullObject) { - found = possibleMetadataRowRange.findOrNullObject('speckle_type', { + found = range.findOrNullObject('speckle_type', { completeMatch: false, // Match the whole cell value. matchCase: true, // Match case. searchDirection: window.Excel.SearchDirection.forward // Start search at the beginning of the range. @@ -239,6 +243,85 @@ async function GetTableApplicationId(table, context) { return tableMetadata['SpeckleTableApplicationId'] } +export async function onTableChanged(eventArgs) { + if (eventArgs.changeType != 'ColumnDeleted') { + return + } + await window.Excel.run(async (context) => { + const tableId = removeNonAlphanumericCharacters(eventArgs.tableId) + let sheet = context.workbook.worksheets.getActiveWorksheet() + let speckleRowMeta = sheet.names.getItemOrNullObject(`speckleRowMetadata_${tableId}`) + await context.sync() + if (speckleRowMeta.isNullObject) { + console.log('speckle row metadata was null') + return + } + let table = sheet.tables.getItem(eventArgs.tableId) + let tableRange = table.getRange() + + let speckleRowMetaRange = speckleRowMeta.getRange() + speckleRowMetaRange.load('columnIndex') + tableRange.load('columnCount, columnIndex') + await context.sync() + + if (tableRange.columnCount == 1 && tableRange.columnIndex == speckleRowMetaRange.columnIndex) { + let speckleColumnMeta = sheet.names.getItemOrNullObject(`speckleColumnMetadata_${tableId}`) + await deleteMetadata(speckleRowMeta, false, context) + await deleteMetadata(speckleColumnMeta, true, context) + } + }) +} +export async function onTableDeleted(eventArgs) { + await window.Excel.run(async (context) => { + const tableId = removeNonAlphanumericCharacters(eventArgs.tableId) + let sheet = context.workbook.worksheets.getActiveWorksheet() + let speckleColumnMeta = sheet.names.getItemOrNullObject(`speckleColumnMetadata_${tableId}`) + let speckleRowMeta = sheet.names.getItemOrNullObject(`speckleRowMetadata_${tableId}`) + await context.sync() + + // warning: must delete rowMetadata (which is actually a column) before deleting the colMetadata + await deleteMetadata(speckleRowMeta, false, context) + await deleteMetadata(speckleColumnMeta, true, context) + }) +} + +async function deleteMetadata(namedRange, isRow, context) { + if (namedRange.isNullObject) { + return + } + + let speckleMetaRange = namedRange.getRange() + + try { + await findMetadataRowIndex(speckleMetaRange, context) + } catch { + console.log('speckle metadata doesnt exist in this range anymore') + return + } + + if (isRow) { + speckleMetaRange.load('rowHidden') + await context.sync() + + if (speckleMetaRange.rowHidden) { + speckleMetaRange.getEntireRow().delete('Up') + } else { + speckleMetaRange.clear('Contents') + } + } else { + speckleMetaRange.load('columnHidden') + await context.sync() + + if (speckleMetaRange.columnHidden) { + speckleMetaRange.getEntireColumn().delete('Left') + } else { + speckleMetaRange.clear('Contents') + } + } + + namedRange.delete() +} + class Base { id totalChildrenCount diff --git a/src/plugins/excel.js b/src/plugins/excel.js index d361eb3..71c72a1 100644 --- a/src/plugins/excel.js +++ b/src/plugins/excel.js @@ -7,8 +7,9 @@ import { getDataTableContainingRange, bakeDataTable, formatArrayDataForTable, - BuildDataTableObject - // getDataTables + BuildDataTableObject, + onTableChanged, + onTableDeleted } from './dataTable.js' const unflatten = require('flat').unflatten @@ -118,16 +119,16 @@ export async function bakeArray(data, context) { } } -export async function bakeTable(data, context, sheet, name, rowStart, colStart) { +export async function bakeTable(data, context, sheet, name, rowStart, colStart, headerRowIndex) { let rowIndex = 0 let batchSize = 50 while (rowIndex < data.length) { let dataBatch = data.slice(rowIndex, rowIndex + batchSize) let numRows = dataBatch.length let rangeAddress = getRangeAddressFromIndicies( - rowStart + rowIndex, + rowStart + headerRowIndex + rowIndex, colStart, - rowStart + rowIndex + numRows - 1, + rowStart + headerRowIndex + rowIndex + numRows - 1, colStart + data[0].length - 1 ) let valueRange = sheet.getRange(rangeAddress) @@ -137,17 +138,43 @@ export async function bakeTable(data, context, sheet, name, rowStart, colStart) } let totalRangeAddress = getRangeAddressFromIndicies( - rowStart, + rowStart + headerRowIndex, colStart, - rowStart + data.length - 1, + rowStart + headerRowIndex + data.length - 1, colStart + data[0].length - 1 ) sheet.activate() - // eslint-disable-next-line no-unused-vars let table = sheet.tables.add(totalRangeAddress, true) - // table.name = name + table.load('id') await context.sync() + + let tableId = removeNonAlphanumericCharacters(table.id) + let columnMetaAddress = getRangeAddressFromIndicies( + rowStart, + colStart + 1, + rowStart, + colStart + data[0].length - 1 + ) + let columnMetaRange = sheet.getRange(columnMetaAddress) + let rowMetaAddress = getRangeAddressFromIndicies( + rowStart, + colStart, + rowStart + headerRowIndex + rowIndex - 1, + colStart + ) + let rowMetaRange = sheet.getRange(rowMetaAddress) + + sheet.names.add(`speckleColumnMetadata_${tableId}`, columnMetaRange) + sheet.names.add(`speckleRowMetadata_${tableId}`, rowMetaRange) + context.workbook.tables.onDeleted.add(onTableDeleted) + context.workbook.tables.onChanged.add(onTableChanged) + + await context.sync() +} + +export function removeNonAlphanumericCharacters(s) { + return s.replace(/\W/g, '') } export function hideRowOrColumn(sheet, columnIndex = -1, rowIndex = -1) { @@ -419,7 +446,6 @@ export async function bakeSchedule( let schedulePaths = [] let flat = flatten(data, { maxDepth: 4 }) - console.log(flat) for (const [key, value] of Object.entries(flat)) { if (key.endsWith('speckle_type') && value.endsWith('DataTable')) {