I am trying to delete the last row in my Excel Online document using Office Scripts.
I do not know what I am doing wrong, it is not deleting, does anyone have an idea?
My code:
function main(workbook: ExcelScript.Workbook) {
let selectedSheet = workbook.getActiveWorksheet();
//getting the used range in the worksheet
let usedRange = workbook.getActiveWorksheet().getUsedRange();
//getting the row count of the used range
let lastRow = usedRange.getRowCount();
//getting the row count of the range
let rowCount = usedRange.getRowCount();
usedRange.getCell(lastRow, 0).getEntireRow().delete(ExcelScript.DeleteShiftDirection.up)
}
This may be a little more foolproof ...
function main(workbook: ExcelScript.Workbook) {
let selectedSheet = workbook.getActiveWorksheet();
let usedRange = selectedSheet.getUsedRange();
let lastRowAddress = usedRange.getLastCell().getAddress();
selectedSheet.getRange(lastRowAddress).getEntireRow().delete(ExcelScript.DeleteShiftDirection.up);
}
Related
I have a code that goes through the "hello" sheet and deletes all of the columns that contain the word B at the top of the column:
let ws = workbook.getWorksheet("hello");
let usedrange = ws.getUsedRange(true);
let qtycol = usedrange.getColumnCount() - 1;
let values = usedrange.getValues();
for (let j = qtycol; j >= 0; j--) {
let command = values[1][j];
if (command == "B") {
usedrange.getColumn(j).delete(ExcelScript.DeleteShiftDirection.left);
}
}
When the file was smaller, there were no issues. But now that the file is a bit larger, I get teh following error:
Line 64: Range getColumn: Timeout
Line 64 is the line that starts with usedrange...
Is there a more efficient way of doing this? Would love to get feedback or other ideas.
Thank you!
I suspect that when a lot of columns are being deleted the updating of the worksheet may be causing your problem.
To get around this, you could build up a multiple-area range (that is a read-only operation that won't modify the worksheet) and then delete it in a single operation.
I don't have access to ExcelScript, but this is the equivalent VBA routine that would do it:
Public Sub bla()
Dim J As Integer
Dim Command As String
Dim qtycol As Integer
Dim ws As Worksheet
Dim UsedRange As Range
Dim toDeleteRange As Range
Set ws = Application.ActiveWorkbook.Worksheets("hello")
Set UsedRange = ws.UsedRange
Let qtycol = UsedRange.Columns.Count - 1
For J = qtycol To 1 Step -1 '(let j = qtycol; j >= 0; j--) {
Let Command = UsedRange(1, J)
If (Command = "B") Then
If (toDeleteRange Is Nothing) Then
Set toDeleteRange = UsedRange.Columns(J)
Else
Set toDeleteRange = Union(toDeleteRange, UsedRange.Columns(J))
End If
End If
Next J
toDeleteRange.Delete (XlDeleteShiftDirection.xlShiftToLeft)
End Sub
You could use the analogous routines from ExcelScript.
Im trying to convert a Macro VBA to a Office Script(Typescript) to run in Excel Web
I have this piece of VBA Code:
Sub process()
On Error GoTo Error_Handler
' concatenate Macro
Dim var As String
Dim row As Integer
Dim column As Integer
Dim concatened As String
Dim hours() As String
Dim cursor As Integer
Dim person As Integer
Dim sum As Double
' zeroing columns
For column = Sheets("Parameters").Cells(2, 4) To Sheets("Parameters").Cells(2, 5)
For row = Sheets("Parameters").Cells(2, 2) To Sheets("Parameters").Cells(2, 3)
Sheets("Projects").Cells(row, column) = ""
Next row
Sheets("Projects").Cells(3, column) = ""
Next column
The context is: I have the main Worksheet who's called Projects, then this loop scan the columns and rows determined by the worksheet called Parameters and erase the data in it
Cells 2,4; 2,5; 2,2; 2,3 just tell them where to start and where to stop by columns and rows
At first I did:
//catch active worksheet
let selectedWorksheet = workbook.getActiveWorksheet();
// select range to scan
let range = selectedWorksheet.getRange("EK3:HL3");
// zeroing columns
range.setValue("");
But I'd like to automate the "EK3:HL3" like the VBA code, to edit by the Parameters worksheet rather than changing manually in the code in case the range EK3:HL3 gets bigger....
If you guys could bright my mind, i'd be truly glad
You could try using getRangeByIndexes.
const wsParameters = Workbook.getWorksheet("Parameters")
const wsProjects = Workbook.getWorksheet("Projects")
const startRow = wsParameters.getRange("B2").getValue()
const startCol = wsParameters.getRange("D2").getValue()
const noRow = wsParameters.getRange("C2").getValue() - startRow + 1
const noCols = wsParameters.getRange("E2").getValue() - startCol + 1
let rng = wsProjects.getRangeByIndexes(startRow, startCol, noRow, noCols)
rng.setValue("")
I built a tracking sheet in Microsoft Excel and later for sharing and work simultaneously I esport it in Google Sheet. I implement this code to a button to save the data I entered in a particular sheet to another one:
Sub SaveInvoice()
Dim Rng As Range, TargetRow As Long
Set Rng = Range("C3,C5,C7,C9,C11")
If Application.WorksheetFunction.CountA(Rng) < Rng.Cells.Count Then
MsgBox ("Please fill in empty cells before saving")
Exit Sub
End If
With Sheets("Invoices")
TargetRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
.Range("A" & TargetRow).Resize(, 5) = Array(Rng.Cells(1), Rng.Cells(3), Rng.Cells(5), Rng.Cells(7), Rng.Cells(9))
End With
Rng = "": Set Rng = Nothing:
End Sub
but I tried to impliment this code in google sheets for same reason but I have a problem because it saves in Invoices cell A4 only
this is the code:
function copy() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName('New Inv Entry');
var Properties = PropertiesService.getScriptProperties();
var lastrow = Properties.getProperty('lastrow');
if(lastrow==null) lastrow=1;
else lastrow = parseInt(lastrow);
Properties.setProperty('lastrow',(lastrow+1));
var v = s1.getRange('A'+lastrow).getValue();
ss.getSheetByName('Invoices').getRange('A4').setValue(v);
};
any help please?
Shouldn't ss.getSheetByName('Invoices').getRange('A4').setValue(v); be ss.getSheetByName('Invoices').getRange('A' + lastrow).setValue(v); instead?
Hereunder I am posting the function that I edit. The problem is when this function is executed, the data entered in New Inv Entry didn't goes to last row but it goes to a row that it have data already in it.
function copy() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName('New Inv Entry');
var Properties = PropertiesService.getScriptProperties();
var lastrow = Properties.getProperty('lastrow');
if(lastrow==null) lastrow=1;
else lastrow = parseInt(lastrow);
Properties.setProperty('lastrow',(lastrow+1));
var v = s1.getRange('C3:G11').getValue();
ss.getSheetByName('Invoices').getRange('A' + lastrow).setValue(v);
};
I wrote a script in Google app script to search a value in a sheet and update the row as per user entered values.It works fine with google sheets.But when I downloaded the document as an excel file, I expected the script to be even downloaded and converted to VBA macro, but that is not happening and since I don't have any experience with writing VBA scripts, is there any tol that can be used to translate the .gs to the VBA.
The following is the function if that helps:
function test() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet2');
var spreadsheet = SpreadsheetApp.getActive();
sheet2.getRange('B5:B7').activate();
var idForSearch = sheet2.getRange("B5").getValue();
var data = sheet1.getDataRange().getValues();
var rownumber;
for(var i = 0; i<data.length;i++){
if(data[i][0] == idForSearch){ //[0] because column A
Logger.log((i+1))
rownumber= i+1;
}
}
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Sheet1'), true);
spreadsheet.getRange('A'+rownumber+':'+'C'+rownumber).activate();
spreadsheet.getRange('Sheet2!B5:B7').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true);
};
thanks in advance for any help.
Please test the next code. I do not have your data to be processed and I made it only theoretically, without testing...
Private Sub testConvert()
Dim actWork As Workbook, sheet1 As Worksheet, sheet2 As Worksheet
Dim data As Variant, i As Long, rownumber As Long, rng As Range
Set actWork = ActiveWorkbook
Set sheet1 = actWork.Sheets("Sheet1")
Set sheet2 = actWork.Sheets("Sheet2")
actWork.Activate
idForSearch = shee2.Range("B5").Value
data = sheet1.Range("B5:B7").Value 'not necessary to be activated
For i = 1 To UBound(data) 'in VBA such an array (created from a range) is 1 based...
If UCase(data(i,1)) = UCase(idForSearch) Then 'VBA is case sensitive
WriteLog i 'you must have a function ('WriteLog') able to do it...
rownumber = i
'if you have only one occurrence, it is good to exit the loop to save time (not for this specific case of 3 times):
Exit For
'If many occurrences may be, you just comment the line above...
End If
Next i
sheet1.Activate 'not necessary
Set rng = sheet1.Range("A" & rownumber & ":" & "C" & rownumber).Select
sheet2.Range("B5:B7").Value = WorksheetFunction.Transpose(rng.Value)
End Sub
The last to code rows transpose the horizontal range of sheet1 on column range of sheet2...
I can help you in function WriteLog creation, if you tell me some more details: What type of log must it be (a text file), on that path to be created, found etc. Do you want to add, append the i value, or would you like to rewrite the existing one if any value already has been recorded?
I use below code to read a .xlsm file:
Workbook wb = WorkbookFactory.create(input);
Sheet sheet = wb.getSheetAt(0);
int firstRow = sheet.getFirstRowNum();
int lastRow = sheet.getLastRowNum();
for (int rownum = firstRow; rownum < lastRow; rownum++) {
Row row = sheet.getRow(rownum);
short firstCell = row.getFirstCellNum();
short lastCell = row.getLastCellNum();
The code works well except at a specific row, there are only 7 cells show in MS Excel, but in the program I got 27 cells, most of them null, only the last few columns with data I couldn't see in MS Excel.
Is it due to the wrong format/data in the xlsm file(how to check if so?), or anything else?