Office Scripts - AutoFill - office-scripts

I am trying to make the column next to another one filled with zeroes when there are values in the column next to it. They become endless though and just go on to infinity. Does anyone know how to make it stop when the column next to it ends as well?
My code:
function main(workbook: ExcelScript.Workbook) {
let selectedSheet = workbook.getActiveWorksheet();
selectedSheet.getRange("U4").setValue("0");
selectedSheet.getRange("U4").autoFill();
}
In this picture, I want the column with zero to only to fill the column where there are numbers to the left, right now it fills the whole column, with no end in sight. Is this possible?

Here's a script that does this using autofill:
function main(workbook: ExcelScript.Workbook) {
let selectedSheet: ExcelScript.Worksheet = workbook.getActiveWorksheet();
selectedSheet.getRange("U4").setValue("0");
let fillRange: ExcelScript.Range = selectedSheet.getRange("T4").getExtendedRange(ExcelScript.KeyboardDirection.down).getOffsetRange(0,1);
selectedSheet.getRange("U4").autoFill(fillRange.getAddress(), ExcelScript.AutoFillType.fillDefault);
}
Alternatively, once you get the filledRange, you can just use the setValue() method to set the values in that range to zero:
function main(workbook: ExcelScript.Workbook) {
let selectedSheet: ExcelScript.Worksheet = workbook.getActiveWorksheet();
let filledRange: ExcelScript.Range = selectedSheet.getRange("T4").getExtendedRange(ExcelScript.KeyboardDirection.down).getOffsetRange(0,1);
offsetRange.setValue(0);
}

Related

TypeScript Function to dynamically set an entire Column range's value to eg. AD1, AD2, AD3, etc

World
I am trying to write a function that will dynamically setValues on the whole range of column AE to "AD" + i (with my assumption that i would be the incrementing value) This is the function I'm using but all it does is write AD5 into the first 5 columns, not AD1, AD2, AD3 etc...
for (let i =1; i <=5; i++) {
// Set AE2 to AE5.
let rowID = range.setValue("AD" + i);
}
I'm sure it is something simple and stupid... Thanks for any help or suggestions!
Here is the complete code:
function main(workbook: ExcelScript.Workbook, sheetName: string, address: string, base64ImageString: string) {
let sheet = workbook.getWorksheet(sheetName);
let range = sheet.getRange("AE2:AE5");
for (let i =2; i <=5; i++) {
// Set AE2 to AE5.
let rowID = range.setValue("AD" + i);
}
}
Thanks!
Yeah, you're loop is actually writing out against all cells in the range variable so every time it goes around, it will write AD1, AD2, AD3, etc. in ALL cells.
Given you're looping 5 times, the last entry written will be AD5 and you don't even see the previous values. You can watch it and you'll see what I mean but don't blink or you'll miss it.
I've modified your script to make it do what you want but with an approach I'd be taking.
function main(workbook: ExcelScript.Workbook, sheetName: string, address: string, base64ImageString: string) {
let sheet = workbook.getWorksheet(sheetName);
let range = sheet.getRange("AE2:AE5");
let rowCount = range.getRowCount();
for (var row = 0; row < rowCount; row++) {
let cellAddress = range.getCell(row, 0).getAddress();
sheet.getRange(cellAddress).setValue(cellAddress.split('!')[1]);
}
}
Have a look, digest it and see if it helps.
I hope I've understood correctly.
you may Misunderstood the meaning of this method range.setValue
when you call the method, it will fill all the range, so all cells are the value of your last traversal
if you want to implement your purpose you could Traverse all cells and set the cell, not the range
I have done this in the past by putting the following in cell A1 and dragging down:
="AD"&row()
Drag as far as needed and copy paste.special values as needed. Never considered using vba though.

Logging to console whenever a cell value exceeds character limit

I have this pseudocode in mind to log an error whenever the length of a cell value within the ItemNumber column exceeds 10 characters. I would also like to display the offending row number as well.
Haven't got a chance to test this out fully, but is it possible?
Any help would be much appreciated!
let itemDesc = newTable.getColumnByName("ItemNumber")
for (let i = itemDesc.length - 1; i >= 0; i--) {
let event = itemDesc[i];
let rowNumber = ???
if (event.length > 10) {
console.log(`Character count exceeds 10 characters at Rows: ${rowNumber}`);
}
}
This code should work. It assumes that the data is in an Excel table / ListObject:
function main(workbook: ExcelScript.Workbook) {
let ws = workbook.getActiveWorksheet();
let newTable = ws.getTable("Table1");
let itemDesc = newTable.getColumnByName("ItemNumber");
let rang = itemDesc.getRange();
let vals = rang.getValues();
let rowNumbers = []
vals.forEach((item, rowNumber) => {
if (rowNumber > 0 && item[0].toString().length > 10) {
rowNumbers.push(rowNumber)
}
})
rowNumbers.forEach(row => console.log(`Character count exceeds 10 characters at Rows: ${row}`)) //prints each offending row on a separate line
console.log(`Character count exceeds 10 characters at Rows: ${rowNumbers.toString()}`); //prints all offending rows on one line
}

After setting a format and writing some values for a given range, that same format is partially and automatically applied to other ranges

I'm not sure if this is an issue or if it is expected behavior from Excel. If it is indeed expected behavior, I would appreciate an explanation about what is happening, since I cannot see a pattern.
If you set a format and some values to a range and then assign only values to another range located below the first one, the format of the first range is applied partially (randomly?) to the new range.
My test function:
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
function loadSampleData(applyFormat) {
var columnCount = 30;
if (applyFormat) {
columnCount = 5;
}
var data = [];
for (var rows = 0; rows < 4; rows++) {
var row = [];
for (var columns = 0; columns < columnCount; columns++) {
var value = columns;
if (getRandomInt(1, 3) == 2) {
value = "text";
}
row.push(value);
}
data.push(row);
}
return Excel.run(function (ctx) {
var selectedRange = ctx.workbook.getSelectedRange().load(['rowCount', 'columnCount']);
var extendedRange;
return ctx.sync().then(function () {
var totalRows = data.length;
var totalColumns = data[0].length;
var deltaRows = totalRows - selectedRange.rowCount;
var deltaColumns = totalColumns - selectedRange.columnCount;
extendedRange = selectedRange.getResizedRange(deltaRows, deltaColumns);
if (applyFormat) {
extendedRange.format.fill.color = "orange";
extendedRange.format.font.color = "white";
}
else {
extendedRange.clear();
}
extendedRange.values = data;
}).then(ctx.sync)
}).catch(errorHandler);
}
Steps:
Create one button (Button A) in the task pane. This button must call loadSampleData and pass true, to write some data and format (fill and font color) to a range. (Range A)
Create another button (Button B) in the task pane. This button must call loadSampleData and pass false, to write only data (no format) to a bigger range (Range B).
Click the A1 cell, then click Button A. Notice the range and format that appears.
Click A6, then click Button B. Notice that a bigger range is written and that some of its cells have the same format as the range in step 3, even though no explicit format was set to the range.
With A6 still selected, click Button B multiple times. Notice that as the values of the range change, the formatted cells change as well.
Notes:
This doesn't happen if Range B is written above Range A.
This doesn't happen if Range B is written 4 (or more) rows below Range A.
Thanks!
Fascinatingly, I can reproduce the issue even in the UI, without programmability. Excel is doing some sort of pattern-matching, though I'll admit I have a hard time deciphering what the pattern is...
I will discuss with our team -- but in terms of concrete guidance, I think your safest bet is to set the values, and then clear the formatting. If you want to be super-careful, you can even take it one step further:
Set number formatting (to ensure that strings vs numbers vs date strings get interpreted as you want them to be)
Set the values
range.clear(Excel.ClearApplyTo.formats);
Re-set the number formatting
I will admit that this seems like a workflow worth improving. Let me see if we can either fix "values", or provide a method that lets you set values and number formats in one go, and in a stricter fashion than what is happening today.

How do I get character count from cell

Goal: I'm trying to add a feature to my Excel 2016 VSTO plugin. The feature will get 1 column from the active sheet, and iterate over it changing the background color based on string length.
Problem: I'm having trouble getting string length from the cells. I can not figure out the proper syntax I currently have var count = row.Item[1].Value2.Text.Length;
Code: Here is what I have
public void CharacterLengthCheck(int length = 24, int Column = 3)
{
Worksheet sheet = Globals.ThisAddIn.Application.ActiveSheet;
var RowCount = sheet.UsedRange.Rows.Count;
Range column = sheet.Range[sheet.Cells[1, Column], sheet.Cells[RowCount, Column]];
foreach (Range row in column)
{
var count = row.Item[1].Value2.Text.Length;
if (count > length)
{
row.Item[1].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);
}
else
{
row.Item[1].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Green);
}
}
}
I think your problem is here:
row.Item[1].Value2.Text.Length
The length function is Len(x), so try Len(row.Item[1].Value2.Text)
Thank you to #Jeeped for their advice on using conditional formatting. However the answer to my original question is.
Change
var count = row.Item[1].Value2.Text.Length;
to
string text = (row.Item[1].Value).ToString();
var count = text.length;
I believe this is because value is dynamic and needs to be explicitly cast to string

Select the fill rows and fill columns (rows and columns with values) from excel file

It's a simple question but I didn't succeed to do it.
I need to run with a loop on the rows and columns with the value - to select the values.
I write a function to do it but with the debug I see that the rows count number is 1048576 and the file has just 32 rows with values (the same happens with the columns)
The function code:
let functionParseXmlToCsv (xmlFile:string , excelFormatFile:string , excelPath:string) =
let xlApp = new Excel.ApplicationClass()
let xlWorkBookInput = xlApp.Workbooks.Open(excelPath + DateTime.Today.ToString("yyyy_dd_MM")+".xlsx")
let listOfRows = ResizeArray<string>()
for tabs in 1 .. xlWorkBookInput.Worksheets.Count do
let listOfCells = ResizeArray<string>()
let xlWorkSheetInput = xlWorkBookInput.Worksheets.[tabs] :?> Excel.Worksheet
let filePath = excelPath + DateTime.Today.ToString("yyyy_dd_MM")+"_"+xlWorkSheetInput.Name+".csv"
//let csvFile = File.Create(filePath)
use csvFile = StreamWriter(filePath, true)
for rowNumber in 1 .. xlWorkSheetInput.Rows.Count do
for columnNumber in 1.. xlWorkSheetInput.Columns.Count do
let cell = xlWorkSheetInput.Cells.[rowNumber,columnNumber]
let value = string cell
listOfCells.Add(value)
let s = String.Join(", ", listOfCells)
csvFile.WriteLine(s)
File.Exists(excelPath + DateTime.Today.ToString("yyyy_dd_MM")+".xlsx")
Could someone help me?
Try if UsedRange fixes your issue. So change your row / column loop to
for rowNumber in 1 .. xlWorkSheetInput.UsedRange.Rows.Count do
and
for columnNumber in 1.. xlWorkSheetInput.UsedRange.Columns.Count do

Resources