Adding Row at End of Dynamic Excel Template

I need to insert a row into an excel sheet, preferably at the end of the current data but at the top would work too. The problem is, the sheet contains a template with headers and 1500+ blank rows as well as any number of rows of actual data as well. Because of this, it is hard to determine where the end of the data is.

I have tried to insert at row 5 every time, this works once but then when it runs again it overwrites the row that was just inserted. I have also tried to get the data into a data table, get the row count, and append to the end…but the template and blank rows make it so there are 1500+ rows even though there are only 10 or so rows of actual data.

Here is an example of the template/data:

If your data is inside Excel as a table, you can use the activity "Append Range/Append after Range = Excel.Table(“Tabela1”)
image

If you are not using a table inside Excel, you can use the “Find First/Last Data Row” activity.

image
Ex:
image

image

The trick is in the “Source Range” setting. You can define it from Ax to A1000000 (1 million), so when the activity finds the last filled cell in that column, it will stop and provide you with the index of that row.

If you don’t know the number of empty rows at the beginning of the Excel sheet, you can read the range and then count the empty values using a loop. Keep iterating until you find a non-empty value and record its index as the starting point for your data. This way, you dynamically determine the position of your data even if there are variable empty rows at the beginning of the sheet.

As last recurse you can try a VB.NET code (something like this):

Imports System
Imports System.Data
Imports System.Linq
Imports System.Threading
Imports System.Collections.Generic
Imports Microsoft.Office.Interop.Excel

Dim excelApp As New ApplicationClass()
Dim workBook As Workbook = excelApp.Workbooks.Open("C:\path\file.xlsx")
Dim workSheet As Worksheet = TryCast(workBook.Sheets("sheet"), Worksheet)

Dim lastRow As Integer = workSheet.Cells(workSheet.Rows.Count, "A").End(XlDirection.xlUp).Row
Dim firstNonEmptyRow As Integer = 0

For i As Integer = 1 To lastRow
    Dim cell As Range = CType(workSheet.Cells(i, 1), Range)
    If cell.Value IsNot Nothing AndAlso Not String.IsNullOrEmpty(cell.Value.ToString()) Then
        firstNonEmptyRow = i
        Exit For
    End If
Next

' Now, 'firstNonEmptyRow' has the index for the first non-empty row.


workBook.Close()
Marshal.ReleaseComObject(workBook)
excelApp.Quit()
Marshal.ReleaseComObject(excelApp)

If you need to add data to existing data …

You can try link query it will add the data to existing one exactly … So won’t required to count the last row which present the data

dt1 =dt1. AsEnumerable(). Union(dt2.AsEnemerable(), DataRowComparer. Default).CopyToDataTable()

@jpreziuso

Thank you for this information. I am attempting to use the Find First/Last Row of Data activity but my source doesn’t have column names. How can I reference the first column without the name?

image

Hi @jpreziuso

If your source doesn’t have column names, you can reference the columns by their index (0-based) rather than by name. In UiPath’s “Find First/Last Row of Data” activity, you can specify the column index

In UiPath, you can specify the column index in the “Column Name” field of the “Find First/Last Row of Data” activity properties as follows:

1.Add the “Find First/Last Row of Data” activity to your workflow.

2.In the “Properties” pane on the right-hand side of the UiPath Studio, look for the “Column Name” property under the “Input” section.

3.Click on the “Column Name” field, and a small icon with three dots (…) should appear on the right side of the field.

4.Click on the icon (…) to open the “Select” window.

5.In the “Select a Column” window, you can specify the column index by simply entering the index number as text. For example, to reference the first column (index 0), you would enter “0” in this field.
6. Click the “OK” button to save your selection.

@jpreziuso

How do I reference the index? Entering just 0 gives and error and I can’t find a function to reference the index

Is your Excel file different from the image you sent? In the image, the headers are not in the first row, but you have them.

Yes there are the headers in column 2, but the source is the whole sheet so I am not sure how to reference the headers

In the column 2 or row 2?
Can you send a screenshot?

image

Headers start in row 2, sorry. But the first row is a merged cell with text as well

Perfect, so you have to configure like this:

image

@jpreziuso Please let me know if it worked :grinning:

I received the following error

image

Source: Find First/Last Data Row

Message: Exception from HRESULT: 0x800A03EC

Exception Type: UiPath.Excel.ExcelException

UiPath.Excel.ExcelException: Exception from HRESULT: 0x800A03EC —> System.Runtime.InteropServices.COMException: Exception from HRESULT: 0x800A03EC at Microsoft.Office.Interop.Excel._Worksheet.get_Range(Object Cell1, Object Cell2)
at UiPath.Excel.ExcelActionExecutor.<>c__DisplayClass5_11.<ExecuteForCurrentWorkbook>b__1() at UiPath.Excel.ExcelContextHelper.Execute[T](Func1 func, ExcelContext context, Object contextParams)
— End of inner exception stack trace —
at UiPath.Excel.ExcelContextHelper.Execute[T](Func1 func, ExcelContext context, Object[] contextParams) at UiPath.Excel.ExcelActionExecutor.ExecuteForCurrentWorkbook[T](Func2 func, String workSheet, String range)
at UiPath.Excel.WorkbookMetadataOperations.GetExcelMetadataForRange(String range, String worksheet, Boolean clipToUsedRange)
at UiPath.Excel.Activities.QuickHandle.RangeRefExtensions.GetAbsoluteDataAddressForRangeColumn(IReadRangeRef range, String columnName, Boolean hasHeaders, IExtendedWorkbook workbook)
at UiPath.Excel.Activities.Business.FindFirstLastDataRowX.<>c__DisplayClass36_0.b__0()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at UiPath.Excel.Activities.Business.FindFirstLastDataRowX.d__36.MoveNext()
— End of stack trace from previous location where exception was thrown —
at UiPath.Shared.Activities.AsyncTaskCodeActivityImplementation.EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
at UiPath.Shared.Activities.AsyncTaskCodeActivity.EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
at System.Activities.AsyncCodeActivity.System.Activities.IAsyncCodeActivity.FinishExecution(AsyncCodeActivityContext context, IAsyncResult result)
at System.Activities.AsyncCodeActivity.CompleteAsyncCodeActivityData.CompleteAsyncCodeActivityWorkItem.Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)

Check List:

  1. The Excel file should be closed before the process starts.
  2. The activity “Find First/Last Data Row” should be inside an “Excel Application Scope”.

It is inside an “Excel Process Scope”, that should be the same thing right?

To solve the issue you could try:

  • add a delay between operation on the Excel file (if the issue comes from two actions on the same file in the short amount of time, or when you open)
  • make sure the Excel process is closed before the Excel Application Scope starts working on a file
    (killing all running Excel processes if necessary)

I actually have both of those already in place. Kill Excel process before opening excel and delays after opening excel. I can try to lengthen the delays

I had this formatted incorrectly, it is now working as expected. Thank you

1 Like

I’m glad to help you :grinning: