admin管理员组文章数量:1026989
In the following VBA code, I debug.print each cell value. Using the data in the picture, my answer appears like this.
Sub loopAndDebugPrintEachCell()
Dim cl As Object
With Sheets("Sheet1")
For Each cl In .Range("A1:D2")
Debug.Print cl.Value
Next cl
End With
End Sub
I am trying to reiterate this code in JavaScript and I figured out a solution, but I am not sure that this is the most efficient way. I am getting the exact same answer, but is there a more advantageous way to loop through a range?
loopAndConsoleLogEachCell = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.worksheets.getItem("Sheet1").getRange("A1:D2");
range.load(["columnCount", "rowCount"]);
await context.sync();
let i = 0;
let rowC = 0;
do {
let loopRng = range.getAbsoluteResizedRange(1, 1).getOffsetRange(rowC, i).load(["values"]);
await context.sync();
console.log(`${loopRng.values} `);
let rangeColCount = Math.floor(((range.columnCount) / 2) + 1);
if (rowC < (range.rowCount) && i == (rangeColCount)) {
rowC++;
i = 0;
} else {
i++;
}
}
while (rowC < range.rowCount && i < range.columnCount);
});
} catch (error) {
console.error(error);
}
};
In the following VBA code, I debug.print each cell value. Using the data in the picture, my answer appears like this.
Sub loopAndDebugPrintEachCell()
Dim cl As Object
With Sheets("Sheet1")
For Each cl In .Range("A1:D2")
Debug.Print cl.Value
Next cl
End With
End Sub
I am trying to reiterate this code in JavaScript and I figured out a solution, but I am not sure that this is the most efficient way. I am getting the exact same answer, but is there a more advantageous way to loop through a range?
loopAndConsoleLogEachCell = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.worksheets.getItem("Sheet1").getRange("A1:D2");
range.load(["columnCount", "rowCount"]);
await context.sync();
let i = 0;
let rowC = 0;
do {
let loopRng = range.getAbsoluteResizedRange(1, 1).getOffsetRange(rowC, i).load(["values"]);
await context.sync();
console.log(`${loopRng.values} `);
let rangeColCount = Math.floor(((range.columnCount) / 2) + 1);
if (rowC < (range.rowCount) && i == (rangeColCount)) {
rowC++;
i = 0;
} else {
i++;
}
}
while (rowC < range.rowCount && i < range.columnCount);
});
} catch (error) {
console.error(error);
}
};
Share
Improve this question
edited Jan 26, 2022 at 19:36
FreeSoftwareServers
2,8526 gold badges40 silver badges74 bronze badges
asked Apr 22, 2020 at 16:34
EthanEthan
8486 silver badges23 bronze badges
1
-
3
In addition to @RaymondLu answer, don't have a
context.sync
in a loop. For details about how to avoid this, see learn.microsoft./en-us/office/dev/add-ins/concepts/…. – Rick Kirkham Commented Apr 23, 2020 at 1:08
3 Answers
Reset to default 3If you want to print the value of each cell in the range, you could use range.values
API
Here is the sample code for getting the values for the range
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getItem("Sample");
const range = sheet.getRange("B2:E6");
range.load("text");
range.load("values");
await context.sync();
console.log(range.values);
//console.log(JSON.stringify(range.text, null, 4));
});
The document can be found https://learn.microsoft./en-us/javascript/api/excel/excel.range?view=excel-js-preview#values
Update:
My original answer searched the entire range starting at row/col 0/0, but I quickly realized a few "gotchas" based on the code (copied from MS somewhere...).
Here is an example where I'm only searching in a column and I'm not starting at row 0.
A few notes:
I changed
r
toi
becauser
makes you thinkrow
but really, its the index of the range which is zero indexed, but could start at row 42.So, when accessing
values
forB2
inside of sayRange("B2:B5")
your value starts with.values[0][0]
.To get the value of Cell
C2
insideRange("B2:C5")
your value would be.values[0][1]
. (0 = first row of RANGE and 1 = second col in range).Using
foo.length
inside loop declaration re-calculates the variable each iteration of the loop, for readability and efficiency, declare your start end variables before loop.var ws = context.workbook.worksheets.getActiveWorksheet(); var rng = ws.getRange("B2:B5"); rng .load(["rowCount", "values"]); return context.sync() .then(function () { var RowCount = rng.rowCount for (var i = 0; i < RowCount; ++i) { var rcellval = rng .values[i][0] console.log(rcellval) } })
Here is an example I used to iterate over a range, only using one context.sync()
to find a cell match via RegEx
which should illustrate how to use a For Each Cell
loop. Keep in mind I am new to JS as well, but I believe this is proper method.
function Bool_RegEx(rexp, findstr) {
return rexp.test(findstr)
}
function Make_FakeData(context) {
var ws = context.workbook.worksheets.getActiveWorksheet();
var rng = ws.getRange("A1:D5");
rng.values = "TESTDATA";
var rng = ws.getRange("A5");
rng.values = "AB12345678"
return context;
}
export async function helloworld(event) {
try {
await Excel.run(async (context) => {
//Start Func
Make_FakeData(context);
var ws = context.workbook.worksheets.getActiveWorksheet();
var rng = ws.getRange("A1:D5");
rng.load(["columnCount", "rowCount", "values"]);
let rexp = new RegExp('[a-z]{2}[0-9]{8}', 'i');
return context.sync()
.then(function () {
for (var r = 0; r < rng.rowCount; ++r) {
for (var c = 0; c < rng.columnCount; ++c) {
var rcellval = rng.values[r][c];
console.log("r = " + r);
console.log("c = " + c);
console.log("rcellval = " + rcellval);
if (Bool_RegEx(rexp, rcellval) === true) {
console.log("RegEx Match in Row r" + r + ", Col " + c);
console.log("RegEx Match rcellval = " + rcellval);
}
}
}
})
//End Func
await context.sync();
});
} catch (error) {
console.error(error);
}
event.pleted();
}
VBA allows you to access every cell on the iteration using the for loop. What I did in TypeScript to replicate this for a range was loading the properties of columns and rows and storing the values in variables:
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getActiveWorksheet();
const range = context.workbook.getSelectedRange();
range.load(["columnIndex", "columnCount", "rowCount", "rowIndex"]);
let col_1 = range.columnIndex; //first column index
let nc = range.columnCount; //number of columns
let row_1 = range.rowIndex; //first row
let nr = range.rowCount; //number of rows
Then you can access each cell with two for loops:
for (let r = 0; r < nr; r++) {
for (let c = 0; c < nc; c++) {
cell = sheet.getCell(r + row_1, c + col_1);
cell.load(["address", "values", "formulasR1C1", "format"]);
await context.sync();
let cell_add = cell.address;
let cell_val = cell.values[0][0]; //values of a cell/range is always a matrix
if (cell_val <= 5) {
//do something
}
}
};
The code might not be the best, but it worked for me.
Hope this helps.
In the following VBA code, I debug.print each cell value. Using the data in the picture, my answer appears like this.
Sub loopAndDebugPrintEachCell()
Dim cl As Object
With Sheets("Sheet1")
For Each cl In .Range("A1:D2")
Debug.Print cl.Value
Next cl
End With
End Sub
I am trying to reiterate this code in JavaScript and I figured out a solution, but I am not sure that this is the most efficient way. I am getting the exact same answer, but is there a more advantageous way to loop through a range?
loopAndConsoleLogEachCell = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.worksheets.getItem("Sheet1").getRange("A1:D2");
range.load(["columnCount", "rowCount"]);
await context.sync();
let i = 0;
let rowC = 0;
do {
let loopRng = range.getAbsoluteResizedRange(1, 1).getOffsetRange(rowC, i).load(["values"]);
await context.sync();
console.log(`${loopRng.values} `);
let rangeColCount = Math.floor(((range.columnCount) / 2) + 1);
if (rowC < (range.rowCount) && i == (rangeColCount)) {
rowC++;
i = 0;
} else {
i++;
}
}
while (rowC < range.rowCount && i < range.columnCount);
});
} catch (error) {
console.error(error);
}
};
In the following VBA code, I debug.print each cell value. Using the data in the picture, my answer appears like this.
Sub loopAndDebugPrintEachCell()
Dim cl As Object
With Sheets("Sheet1")
For Each cl In .Range("A1:D2")
Debug.Print cl.Value
Next cl
End With
End Sub
I am trying to reiterate this code in JavaScript and I figured out a solution, but I am not sure that this is the most efficient way. I am getting the exact same answer, but is there a more advantageous way to loop through a range?
loopAndConsoleLogEachCell = async () => {
try {
await Excel.run(async context => {
const range = context.workbook.worksheets.getItem("Sheet1").getRange("A1:D2");
range.load(["columnCount", "rowCount"]);
await context.sync();
let i = 0;
let rowC = 0;
do {
let loopRng = range.getAbsoluteResizedRange(1, 1).getOffsetRange(rowC, i).load(["values"]);
await context.sync();
console.log(`${loopRng.values} `);
let rangeColCount = Math.floor(((range.columnCount) / 2) + 1);
if (rowC < (range.rowCount) && i == (rangeColCount)) {
rowC++;
i = 0;
} else {
i++;
}
}
while (rowC < range.rowCount && i < range.columnCount);
});
} catch (error) {
console.error(error);
}
};
Share
Improve this question
edited Jan 26, 2022 at 19:36
FreeSoftwareServers
2,8526 gold badges40 silver badges74 bronze badges
asked Apr 22, 2020 at 16:34
EthanEthan
8486 silver badges23 bronze badges
1
-
3
In addition to @RaymondLu answer, don't have a
context.sync
in a loop. For details about how to avoid this, see learn.microsoft./en-us/office/dev/add-ins/concepts/…. – Rick Kirkham Commented Apr 23, 2020 at 1:08
3 Answers
Reset to default 3If you want to print the value of each cell in the range, you could use range.values
API
Here is the sample code for getting the values for the range
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getItem("Sample");
const range = sheet.getRange("B2:E6");
range.load("text");
range.load("values");
await context.sync();
console.log(range.values);
//console.log(JSON.stringify(range.text, null, 4));
});
The document can be found https://learn.microsoft./en-us/javascript/api/excel/excel.range?view=excel-js-preview#values
Update:
My original answer searched the entire range starting at row/col 0/0, but I quickly realized a few "gotchas" based on the code (copied from MS somewhere...).
Here is an example where I'm only searching in a column and I'm not starting at row 0.
A few notes:
I changed
r
toi
becauser
makes you thinkrow
but really, its the index of the range which is zero indexed, but could start at row 42.So, when accessing
values
forB2
inside of sayRange("B2:B5")
your value starts with.values[0][0]
.To get the value of Cell
C2
insideRange("B2:C5")
your value would be.values[0][1]
. (0 = first row of RANGE and 1 = second col in range).Using
foo.length
inside loop declaration re-calculates the variable each iteration of the loop, for readability and efficiency, declare your start end variables before loop.var ws = context.workbook.worksheets.getActiveWorksheet(); var rng = ws.getRange("B2:B5"); rng .load(["rowCount", "values"]); return context.sync() .then(function () { var RowCount = rng.rowCount for (var i = 0; i < RowCount; ++i) { var rcellval = rng .values[i][0] console.log(rcellval) } })
Here is an example I used to iterate over a range, only using one context.sync()
to find a cell match via RegEx
which should illustrate how to use a For Each Cell
loop. Keep in mind I am new to JS as well, but I believe this is proper method.
function Bool_RegEx(rexp, findstr) {
return rexp.test(findstr)
}
function Make_FakeData(context) {
var ws = context.workbook.worksheets.getActiveWorksheet();
var rng = ws.getRange("A1:D5");
rng.values = "TESTDATA";
var rng = ws.getRange("A5");
rng.values = "AB12345678"
return context;
}
export async function helloworld(event) {
try {
await Excel.run(async (context) => {
//Start Func
Make_FakeData(context);
var ws = context.workbook.worksheets.getActiveWorksheet();
var rng = ws.getRange("A1:D5");
rng.load(["columnCount", "rowCount", "values"]);
let rexp = new RegExp('[a-z]{2}[0-9]{8}', 'i');
return context.sync()
.then(function () {
for (var r = 0; r < rng.rowCount; ++r) {
for (var c = 0; c < rng.columnCount; ++c) {
var rcellval = rng.values[r][c];
console.log("r = " + r);
console.log("c = " + c);
console.log("rcellval = " + rcellval);
if (Bool_RegEx(rexp, rcellval) === true) {
console.log("RegEx Match in Row r" + r + ", Col " + c);
console.log("RegEx Match rcellval = " + rcellval);
}
}
}
})
//End Func
await context.sync();
});
} catch (error) {
console.error(error);
}
event.pleted();
}
VBA allows you to access every cell on the iteration using the for loop. What I did in TypeScript to replicate this for a range was loading the properties of columns and rows and storing the values in variables:
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getActiveWorksheet();
const range = context.workbook.getSelectedRange();
range.load(["columnIndex", "columnCount", "rowCount", "rowIndex"]);
let col_1 = range.columnIndex; //first column index
let nc = range.columnCount; //number of columns
let row_1 = range.rowIndex; //first row
let nr = range.rowCount; //number of rows
Then you can access each cell with two for loops:
for (let r = 0; r < nr; r++) {
for (let c = 0; c < nc; c++) {
cell = sheet.getCell(r + row_1, c + col_1);
cell.load(["address", "values", "formulasR1C1", "format"]);
await context.sync();
let cell_add = cell.address;
let cell_val = cell.values[0][0]; //values of a cell/range is always a matrix
if (cell_val <= 5) {
//do something
}
}
};
The code might not be the best, but it worked for me.
Hope this helps.
本文标签: For Each Cell LoopExcel JavaScript APIStack Overflow
版权声明:本文标题:For Each Cell Loop - Excel JavaScript API - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745655769a2161587.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论