I am creating a vb.net application to update an excel spreadsheet.
I access the excel file using Imports Microsoft.Office.Interop.
So far I can add data to the desired worksheet using hardcoded cell co-ordinates, for example :
sheet.Cells(3, 3) = mystring
I need to loop through each row to find the first row where each of the first 10 cells (A-J) contain no data so I can update those cells. I need to do it this way as columns K onwards may contain other data so I cant check for whole blank rows.
My attempt has started off just checking cell A in each row to begin with, trying to identify a blank/empty cell. If it worked I was thinking about using a for loop inside the do while loop too move along the cells in the row.
Using the following code I get a message box stating "System.__ComObject".
Dim rowcount As Integer = 0
Dim emptyrowfound As Boolean = False
Do While emptyrowfound = False
rowcount += 1
MessageBox.Show(sheet.Cells(rowcount, 1).ToString) ' attempt to view cell contents for testing purposes
If sheet.Cells(rowcount, 1).ToString = "" Then ' attempt to test if cell is blank/empty
emptyrowfound = True
End If
Loop
Once working I intend to apply cell updates like :
sheet.Cells(rowcount, 3) = mystring
...
Can anyone suggest a better way of checking and getting the row number?
First, I would do my check by starting in the 10th column and working left for each row using a Range object. You can use Range.End(xlleft) to check all cells to the left of the specified cell - it will stop at the first nonempty cell, which you are expecting to be in the first column. You should then be able to use the Range.Row property to return the row number of the cell you desire.
Below is a code snippet I dug up, hope it is useful.
For iRow = 1 To 5
For iCol = 1 To 10
IsFist10ColEmpty = True
Cellval = oxlsworksheet.Range(oxlsworksheet.Cells(iRow, iCol).Address(RowAbsolute:=False, ColumnAbsolute:=False)).Value
If Len(Cellval) > 0 Then
IsFist10ColEmpty = False
Exit For
End If
Next
If IsFist10ColEmpty = True Then
MessageBox.Show(iRow & "Rows's First 10 cols are empty.")
End If
Next
working line for you is :
Cellval = oxlsworksheet.Range(oxlsworksheet.Cells(iRow, iCol).Address(RowAbsolute:=False, ColumnAbsolute:=False)).Value
Originally I got answer from Anders Lindahl
link is :
Anders Lindahl's original answer
Related
I am trying to input a value into the next empty row in a column.
I tried using rows.count and off setting it like you would with a paste but it doesn't work. I was able to get it to change the value in the first cell but not to look for the next empty and change its value.
Private Sub CommandButton1_Click()
Dim wbCount As Workbook
Set wbEntry = ThisWorkbook
wbEntry.ActiveSheet.Range("B3").Copy
Set wbCount = Workbooks.Open("U:\MO# Count.xlsm")
Worksheets("Golf Cart").Paste _
Destination:=Worksheets("Golf Cart").Range("V5")
Worksheets("Golf Cart").Range("C2").Value = 1
wbEntry.Activate
Application.CutCopyMode = False
wbEntry.ActiveSheet.Range("O1").Select
End Sub
What I have works except for not searching for the next empty cell in "C" and changing the value to "1".
I'm confused, why would you think it searches for an empty cell?
Leaving the rest of the macro alone for now, this line:
Worksheets("Golf Cart").Range("C2").Value = 1
Does not search for an empty cell, it just writes a "1" into Cell C2. If you would like it to find the first empty cell in column C and then write a 1 into it, then this should do the trick:
Worksheets("Golf Cart").Cells(Sheets("Golf Cart").Cells(Rows.Count, 3).End(xlUp).Row + 1, 3) = 1
I'm not sure thats what you want tho, please clarify. This finds the last used row in column C and then goes to the next one down to write a "1" into it. It doesnt work if you want to find empty cells in an otherwise value-filled column. But you wrote something about rows.count or something, so I thought I'd post that way?
I have a vba formula that copies a value (which consists in a number) of a cell to another cell. When the number is with decimals (ex: 25,50), the result is ok, but when the number is without decimals (ex: 50), I get an error checking flag suggesting me to convert that cell to number.
I wouldn't have a problem with this error flagging, but I cannot use the result in a formula. For example, if I use SUM(A:A), the formula adds all the numbers, except the flagged ones.
So far, I have tried pasting using the .xlPasteValuesAndNumberFormats property, without any success.
Sub Adauga()
Dim i As Range
Dim cellTaxa As Range
Set cellTaxa = ActiveSheet.Buttons(Application.Caller).TopLeftCell.Offset(1, -2) 'Here I set the range to the value of a cell that is related to the button I click.
n = 2
Set i = Sheets("TJT DETERMINABILA").Cells(n, 10) 'Here I insert the first result
Do While i <> "" 'Here I find the next empty cell in the same column to insert the value.
n = n + 1
Set i = Sheets("TJT DETERMINABILA").Cells(n, 10)
Loop
cellTaxa.Copy 'Here I copy the cell
i.PasteSpecial xlPasteValues 'Here I paste the cell.
End Sub
I would like to be able to use the values that are pasted in the column I mentioned in the code with the SUM formula.
Thank you!
As #urdearboy has stated, an easy trick to convert text to numbers is to add +0.
In my case, I have added cellTaxa = CellTaxa + 0 before the line cellTaxa.Copy and it has solved my issue.
I'm building an Excel sheet to help me with teaching.
My objective is a sheet to create two random numbers, calculate their arithmetic means and geometric means, and compare them. This part I have finished.
I created a macro and two functions that generates random numbers, then input the numbers to the desired cells:
Sheets("Sheet1").Range("L1").Value = NewRandom()
Sheets("Sheet1").Range("M1").Value = NewRandom2()
I created a button to execute the macro.
How could I make a record of what I have been generating, in designated area U7:V200, on the same sheet?
My aim: The first time I click the button, two generated numbers will be recorded on U7 and V7, respectively. The second time I click, two generated numbers will be recorded on U8 and V8, and so on.
The subroutine below will find the next empty row based on the "U" column of your sheet.
XLROW signifies the row in which you want to begin your search for an empty row.
Once the empty row is found, the two random values that you have passed to the subroutine will be entered into the first available empty row.
Make sure to change "Sheet1" to the name, if you have one, of the sheet that you are using in excel.
Public Sub NEXTEMPTY(VAL1 As Integer, VAL2 As Integer)
Dim XLROW As Integer
XLROW = 7
Do Until Sheet1.Range("U" & XLROW) = ""
XLROW = XLROW + 1
Loop
Sheet1.Range("U" & XLROW).Value = VAL1
Sheet1.Range("V" & XLROW).Value = VAL2
End Sub
Then you can just call the sub anywhere you'd like using:
Call NEXTEMPTY(RANDOM1, RANDOM2)
EDIT: You can also use this in the Do Until. This is more preferable.
Do Until IsEmpty(Sheet1.Range("U" & XLROW))
This is just a matter of finding the last row and pasting to it...
dim lr as long
lr = cells(rows.count,"U").end(xlup).row
cells(lr+1,"U").value = randomnumber1
cells(lr+1,"V").value = randomnumber2
Assumes you are always having U/V paired together, so only need 1 last row
I've set up a two-dimensional array, and I want to count the number of filled cells in column H for each trial in each block. I then want to print the number of filled cells next to the last row of data for each trial, into column T.
The problem I'm getting is that when I try to run the macro, Excel stops responding, and after restarting, I get the error message in the title.
Here is the code:
Sub dotcountanalysis2()
' create multidimensional array
Dim Participant() As Variant
Participant = Worksheets("full test").Range("A7", Range("S:S")).Value
Dim Block As Variant
Block = Columns(2)
Dim Trial As Variant
Trial = Columns(3)
' define column H as boolean variable
Dim Pressed As Boolean
Pressed = True
' begin analysis after practice trials
For Each Block In Participant
For Each Trial In Participant
pressedcount = Range("H:H").Cells.SpecialCells(xlCellTypeConstants).Count
If Cells(, 8) = Pressed Then
Range("T:T").Value = pressedcount
End If
Next Trial
Next Block
End Sub
The error is on line:
pressedcount = Range("H:H").Cells.SpecialCells(xlCellTypeConstants).Count
I'm also not sure that my syntax is correct to make it count for each trial, as I have tried stepping into the code, and it gives the total number of filled cells in column H (562), and prints it in every cell in column T. I think it's also going way past the 7011 rows of data I have, to the maximum possible number of rows.
Here is a sample of my data
The most relevant problem is probably the fact that you create a huge variant array of values and then loop two times through it's values.
The Participant array contains 1048576*19 = 19922944 values. (assuming 1048576 rows in your sheet)
Now you loop through these values and for every value you loop through each value again, giving you 19922944*19922944 = 396923697627136 iterations. So that's why excel doesn't respond.
However, within each iteration, you don't even use the value...?
If you want to calculate that number of Pressed in column H and write that number to column T, why would you load all values of columns A to S into the array?
Here is what I would do in VBA
Dim pressedCount As Long
Dim myCell As range
Dim pressedRange As range
With Worksheets("full test")
pressedCount = Application.WorksheetFunction.CountA(.Columns("H"))
If pressedCount = 0 Then Exit Sub 'make sure there are cells or else the next line will fail
Set pressedRange = .Columns("H").SpecialCells(xlCellTypeConstants)
For Each myCell In pressedRange.Cells 'only loop through the cells containing something
.Cells(myCell.Row, "T").Value = pressedCount
Next myCell
End With
I used the With block so I don't have to write the sheet before every range which you should because otherwise it assumes you mean the active sheet.
Note that this assumes that there can be no other values than "Pressed" in column H, not even a header. If there is a header, start at row 2 and use .Range(.Cells(2, "H"), .Cells(.Rows.Count, "H")) instead of .Columns("H")
However this could also be achieved using a Formula like =IF($H7="Pressed",COUNTA(H:H),"")
I've got an amount of data copied from a table in a .pdf that when pasted into excel puts it all into one column. There are actually multiple pages each with it's own table (the data is one continuous long table split over multiple pages more accurately) and at the top of each page is a series of lines that I'm not interested in (the same unwanted data is at the top of each page). What I am interested in is re-sorting the data under the headers as it is in the table on the original .pdf document, removing the headers in the process. The data as it has been pasted into one column essentially is a list of items in plain text for x rows, followed by a list of start dates for x rows, and then a list of end dates for x rows, repeated every page.
I've figured out how to count the number of lines I don't want by getting a macro to look for the first piece of data I'm interested in ("AAAA") starting at cell (B2);
Cells(2, 2).Select
For i = 1 To 50
If ActiveCell = "AAAA" Then
Exit For
End If
ActiveCell.Offset(1, 0).Select
Next i
Cells(2, 3) = i
If i = 51 Then
Range("B3") = "Cannot find data"
End If
Which starts a search at cell (B2) looking downwards until it finds "AAAA" it then prints how many rows it has moved downwards to find it in cell (C2).
I now wish to be able to start at the cell it has just found [(B34) in this case] and count downwards until it finds the first cell containing a date.
Ultimately I'll need to then count down the same number of cells to find the associated end date and print them all in one row, continuing for the entire column of data.
If anybody could help me with being able to start at the first cell "AAAA" and then count downwards until a date is found, that would be really helpful.
My biggest challeng is to understand what you want to be true. I tryed to make a list of the things what you want.
You have a PDF that when paste in Excel it transform all the
document in one column.
There is a header in each of the Excel pages that you want to delete.
After you find a header you want to find two dates, and they have the same distance from the header.
How I would do it:
For iCounter = 1 to Cells(1048576, 1).End(xlUp).Row
If Cells(iCounter,1) = "YOUR HEADER HERE" then
For kCounter = iCounter to Cells(1048576, 1).End(xlUp).Row
If IsDate(Cells(kCounter,1)) = true then
initialDate = Cells(kCounter,1)
endDate = Cells(2*kCounter-iCounter,1)
End if
Next kCounter
End if
Next iCounter
The following piece of code starts in cell A1 and searches downward until it finds a cell containing a date value. The code only searches until it reaches the last record in the first column (to avoid searching all the way down to the bottom of the sheet if no date is found).
Sub FindFirstDate()
Dim i As Long
For i = 1 To ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
If IsDate(ActiveSheet.Cells(i, 1).Value) = True Then Exit For
Next i
MsgBox "The first cell with a date is " & ActiveSheet.Cells(i, 1).Address
End Sub
In this example the address of the cell with the first date in returned in a MsgBox.