I just wonder whether we can find and replace using Office Excel JS? I have read through their doc but it does not mention about this functionality.
The Range object has a find method to search for a specified string within the range. It returns the range of the first cell with matching text.
await Excel.run(async (context) => {
let sheet = context.workbook.worksheets.getItem("Sample");
let table = sheet.tables.getItem("ExpensesTable");
let searchRange = table.getRange();
let foundRange = searchRange.find("Food", {
completeMatch: true, // Match the whole cell value.
matchCase: false, // Don't match case.
searchDirection: Excel.SearchDirection.forward // Start search at the beginning of the range.
});
foundRange.load("address");
await context.sync();
console.log(foundRange.address);
});
See Find a string within a range using the Excel JavaScript API for more information.
This function replaceAll would do it
Related
I have created a script that will move an entire row to another tab on the worksheet if certain text is entered into a selected cell.
I want to be able to do this if the cell is not empty rather than having certain text and I would like the row to be deleted all except the first column.
The script is below and works really well, I'm not great at coding and managed to cobble this together from some other scripts i found but i now can't manage to edit it to fit this new task.
I tried using Javascript not equals signs and other symbols and can remove rows that are empty but i can't seem to make it work.
function main(workbook: ExcelScript.Workbook) {
// You can change these names to match the data in your workbook.
const TARGET_TABLE_NAME = 'TableNAdded';
const SOURCE_TABLE_NAME = 'TableN';
// Select what will be moved between tables.
const FILTER_COLUMN_INDEX = 27;
const FILTER_VALUE = 'Y';
// Get the Table objects.
let targetTable = workbook.getTable(TARGET_TABLE_NAME);
let sourceTable = workbook.getTable(SOURCE_TABLE_NAME);
// If either table is missing, report that information and stop the script.
if (!targetTable || !sourceTable) {
console.log(`Tables missing - Check to make sure both source (${TARGET_TABLE_NAME}) and target table (${SOURCE_TABLE_NAME}) are present before running the script. `);
return;
}
// Save the filter criteria currently on the source table.
const originalTableFilters = {};
// For each table column, collect the filter criteria on that column.
sourceTable.getColumns().forEach((column) => {
let originalColumnFilter = column.getFilter().getCriteria();
if (originalColumnFilter) {
originalTableFilters[column.getName()] = originalColumnFilter;
}
});
// Get all the data from the table.
const sourceRange = sourceTable.getRangeBetweenHeaderAndTotal();
const dataRows: (number | string | boolean)[][] = sourceTable.getRangeBetweenHeaderAndTotal().getValues();
// Create variables to hold the rows to be moved and their addresses.
let rowsToMoveValues: (number | string | boolean)[][] = [];
let rowAddressToRemove: string[] = [];
// Get the data values from the source table.
for (let i = 0; i < dataRows.length; i++) {
if (dataRows[i][FILTER_COLUMN_INDEX] === FILTER_VALUE) {
rowsToMoveValues.push(dataRows[i]);
// Get the intersection between table address and the entire row where we found the match. This provides the address of the range to remove.
let address = sourceRange.getIntersection(sourceRange.getCell(i, 0).getEntireRow()).getAddress();
rowAddressToRemove.push(address);
}
}
// If there are no data rows to process, end the script.
if (rowsToMoveValues.length < 1) {
console.log('No rows selected from the source table match the filter criteria.');
return;
}
console.log(`Adding ${rowsToMoveValues.length} rows to target table.`);
// Insert rows at the end of target table.
targetTable.addRows(-1, rowsToMoveValues)
// Remove the rows from the source table.
const sheet = sourceTable.getWorksheet();
// Remove all filters before removing rows.
sourceTable.getAutoFilter().clearCriteria();
// Important: Remove the rows starting at the bottom of the table.
// Otherwise, the lower rows change position before they are deleted.
console.log(`Removing ${rowAddressToRemove.length} rows from the source table.`);
rowAddressToRemove.reverse().forEach((address) => {
sheet.getRange(address).delete(ExcelScript.DeleteShiftDirection.up);
});
// Reapply the original filters.
Object.keys(originalTableFilters).forEach((columnName) => {
sourceTable.getColumnByName(columnName).getFilter().apply(originalTableFilters[columnName]);
});
}
If I understand your question correctly, you are currently filtering the table if the value = "Y" (the value assigned to FILTER_VALUE). This part is happening here:
if (dataRows[i][FILTER_COLUMN_INDEX] === FILTER_VALUE) {
You'd like to update this line from checking if the cell value is Y to checking if the cell value is not empty. To do this, you can update this line like so:
if (dataRows[i][FILTER_COLUMN_INDEX] as string !== "") {
I'm trying to retrieve values from disjointed cells (RangeAreas) in an Excel web add-in but I'm struggling to figure out how to do so. In contiguous cells, I can use the "values" property of the Range class as follows:
let currentWorksheet = context.workbook.worksheets.getActiveWorksheet();
let foundRange = currentWorksheet.getRange("A1:A5").load("values");
return context.sync().then(function () {
console.log(JSON.stringify(foundRange.values));
});
How can I do that with disjointed cells on the RangeAreas class? I can't find this documented anywhere. This is my code to get a RangeAreas of disjointed cells and where I can successfully get their "address", but how can I get their "value"?
let currentWorksheet = context.workbook.worksheets.getActiveWorksheet(); // Get active worksheet
let foundRangeAreas = currentWorksheet.findAll("My Keyword", { completeMatch: false, matchCase: false });
foundRangeAreas.load("address");
return context.sync().then(function () {
console.log(JSON.stringify(foundRangeAreas.address));
});
You could use RangeAreas.areas property which returns a collection of rectangular ranges and load values for each range:
foundRangeAreas.load("areas/values");
For more information, check: Excel Range Areas
I have a Workbook that requires it to interact with another workbook. I have the below code which will run fine and get the value of the cell. But I need there to be a function to reference another Workbook.
function main(workbook: ExcelScript.Workbook) {
// Get Worksheet
let Sheet1 = workbook.getWorksheet('Worksheet 1');
// Get the value of cell A1.
let range = SourceData1.getRange("A1");
// Print the value of A1.
console.log(range.getValue());
}
I've tried referencing like so...
let SourceData1 = workbook.getWorksheet('https://mydomain.sharepoint.com/personal/Documents/[sourceData.xlsx]in');
But I take it the workbook part just references whatever is open? How do I refer an external workbook from a different sheet?
You should be able to use most of the response I wrote here. There are just a few small differences:
You do not need to stringify or parse anything. You can just work with the value of the cell as a string directly.
You would get the value of the cell in the first script using the range's GetValue method. You would then return that value as a string in the first script like so:
//first script
function main(workbook: ExcelScript.Workbook): string
{
let sh: ExcelScript.Worksheet = workbook.getActiveWorksheet();
let rang: ExcelScript.Range = sh.getRange("E1");
return rang.getValue() as string
}
In the second script, you wouldn't need to resize any ranges. Just set the range where the input value should be assigned, and assign the functions' parameter value to that (in my link I called the parameter tableValues. So since this is a cell value, I'd consider renaming it to something like cell value). So if you had a cellValue parameter you could just update the line of code like so:
//second script
function main(workbook: ExcelScript.Workbook, cellValue: string)
{
let sh: ExcelScript.Worksheet = workbook.getActiveWorksheet()
let rang: ExcelScript.Range = sh.getRange("D1")
rang.setValue(cellValue)
}
I am new to using excel scripts with power automate. Trying to convert some data to a table. The thing is the number of rows will differ each time.
I've done this in excel desktop, but not sure how to do it using an excel script.
The problem is finding the used range in excel(Office Scripts). Once you have it, i assume you know how to convert it to table.
function main(workbook: ExcelScript.Workbook)
{
// Get the current, active worksheet.
let currentWorksheet = workbook.getActiveWorksheet();
// Get the range containing all the cells with data or formatting.
let usedRange = currentWorksheet.getUsedRange();
// Log the range's address to the console.
console.log(usedRange.getAddress());
}
Link for your reference
From:
https://learn.microsoft.com/en-us/office/dev/scripts/resources/samples/excel-samples
function main(workbook: ExcelScript.Workbook) {
// Get the current worksheet.
let selectedSheet = workbook.getActiveWorksheet();
// Create a table with the used cells.
let usedRange = selectedSheet.getUsedRange();
let newTable = selectedSheet.addTable(usedRange, true);
// Sort the table using the first column.
newTable.getSort().apply([{ key: 0, ascending: true }]);
}
I have the below table (example) with thousand of rows that consists of a column of Request ID and a column of Request ID URL.
How can I hyperlink the Request ID URL into the Request ID text column using VBA or Macro, so that when people click on the ID it will be redirected to the URL.
I do not wish to add another column and use the HYPERLINK formula like =HYPERLINK(B2,A2). I wish the link can directly embedded into the existing
Thank you!
I have resolved my own questions by writing a very basic code snippet using Excel Script Lab.
Just need to figure out how do get a dynamic range in Script Lab, as the Excel sheet range might be various from time to time...
Code as per below.
async function run() {
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getActiveWorksheet();
let reqID = sheet.getRange("A2:A6");
reqID.load("values");
let reqURL = sheet.getRange("B2:B6");
reqURL.load("values");
await context.sync();
for(let i=0;i<reqID.values.length;i++){
let cellRange = reqID.getCell(i,0);
let cellText = reqID.values[i][0];
let cellURL = reqURL.values[i][0];
let hyperlink ={
textToDisplay: cellText,
address: cellURL
}
cellRange.hyperlink = hyperlink;
}
});
}