Adding a new row of data after the last - excel

I have a list of data on my Excel file. I want to add new elements to this list by using a userform.
The code below should add the data on column B, one after the data on the last row.
The problem is each time I add a new data, my code deletes the old data.
So if I have data on column B line 3, it deletes what is in line 3 (the last row) and adds what I've just entered in that line.
Private Sub CommandButton1_Click()
Dim ws_liste As Worksheet
Dim fin_liste As Integer
Set ws_liste = ActiveWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value)
fin_liste = ws_liste.Range("A" & Rows.Column).End(xlUp).Row
'fin_liste = ws_liste.Range("A65533").End(xlUp).Row
ws_liste.Cells(fin_liste + 1, 2) = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
Unload Me
End Sub

I don't understand why you use this code
fin_liste = ws_liste.Range("A" & Rows.Column).End(xlUp).Row
It always give you value "1" and never change, that's why the new data will delete the old one.
I'll give you two solutions, choose what you want.
First, take one cell to save a value from fin_liste as integer (for example I choose cell "D1"). Then add "i" for a new variable as integer.
Here the code.
Private Sub CommandButton1_Click()
Dim ws_liste As Worksheet
Dim fin_liste, i As Integer
Set ws_liste = ActiveWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value)
fin_liste = ws_liste.Range("A" & Rows.Column).End(xlUp).Row
i = Range("D1").Value + fin_liste
'fin_liste = ws_liste.Range("A65533").End(xlUp).Row
ws_liste.Cells(i + 1, 2) = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
Range("D1").Value = i
Unload Me
End Sub
But there's a risk, if value in "D1" has changed, it make your data in a mess.
Second option.
Private Sub CommandButton1_Click()
Dim fin_liste As Range
Set fin_liste = ThisWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value).Cells(Rows.Count, "B").End(xlUp).Offset(1, 0)
'fin_liste = ws_liste.Range("A65533").End(xlUp).Row
fin_liste = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
Unload Me
End Sub

ws_liste.Range("A" & Rows.Column).End(xlUp).Row will evaluate to the first row in the range due to the xlUp parameter.
Since you are adding one to the row index in the following line (ws_liste.Cells(fin_liste + 1, 2)), I am assuming you are trying to refer to the last row of the range. You can achieve this by using xlDown instead of xlUp.
fin_liste = ws_liste.Range("A1").End(xlDown).Row
Edit: As SJR noted, If there is no data in column A, using xlDown on A1 will not find the last row of the data, but instead the next non-blank cell in column A. Instead using xlDown on the column that contains the last row of data would be correct.

Related

Adding items by keeping the order vba

I have the bellow list, where I should add items in column B in each sheet ; liste_lameM1, liste_lameM2, liste_lameM3 et liste_lameM4:
enter image description here
I need to set a condition on the numbers of the column A, to add new item I need to specify the model from a combobox where i have 4 options( M1, M2, M3, M4) to choose the sheet where the item should be added (this part works well).
The second condition is to select a number from 001 to 300 from a combobox to be able to add my item in the correct place on column B, so if I choose 006, modele M1 my data should be in column B, line 7 in worksheet liste_lameM1, if I choose 007, modele M1 my data should be in column B line8 worksheet liste_lameM1, if I choose 010 , modele M2, my data is added on column B line 11 worksheet liste_lameM2 and so on.
here is my code:
Private Sub CommandButton1_Click()
Dim fin_liste As Range, ligne As Long, ws_lame As Worksheet, ctrl As Boolean
Set ws_lame = ActiveWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value)
Set fin_liste = ThisWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value).Cells(Rows.Count, "B").End(xlUp).Offset(1, 0)
For j = 2 To fin_liste
If ws_lame.Range("A" & j) = Me.ComboBox_Num.Value Then
ctrl = True
fin_liste = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
Exit For
End If
Next
If ctrl = False Then
j = fin_liste + 1
ws_lame.Range("A" & j).Value = Me.ComboBox_Num.Value
fin_liste = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
End If
End Sub
The problem with my code is that it is not respecting the numbers I am choosing, it just adds the items one after the other, what editing should I make ? thanks
Variable "j" for looping, I change to "ligne".
Based on your explanation, you can't make the second condition if you use this code as I give you before.
fin_liste = ThisWorkbook.Worksheets(combo.Value).Cells(Rows.Count, "B").End(xlUp).Offset(1, 0)
So even you choose number between 001 & 300, it still add the data exactly on the last row at column "B".
For example, if the last data on cell "B3" (B4 still empty) then you choose number 5 (you hope the data will add on "B6"), the data will add on "B4".
Then maybe you'll find that you can change the .offset(ComboBox_Num.Value, 0), but it will make your data in a mess.
So the code that I give you before ineffective for the 2nd condition.
Based on the 2nd condition, you can use this.
fin_liste = ThisWorkbook.Worksheets(combo.Value).Cells(ComboBox_Num.Value, "B").offset(1, 0)
I still write .offset(1, 0), because I think you want to add the first data on cell "B2", right?
Actually that code have a problem, but based on you question, I think that problem will not affect you. You'll find it out soon. (You should consider Zac's comment)
I've rewrite your code so I can try it on my excel easier. You can change it into your version.
Private Sub CommandButton1_Click()
Dim fin_liste As Range, ligne As Long, ws_lame As Worksheet, ctrl As Boolean
Set ws_lame = ActiveWorkbook.Worksheets(combo.value)
Set fin_liste = ThisWorkbook.Worksheets(combo.Value).Cells(combo2.Value, "B").Offset(1, 0) '.End(xlUp).Offset(combo2.Value, 0)
For ligne = 2 To fin_liste
If ws_lame.Range("A" & ligne) = combo2.Value Then
ctrl = True
fin_liste = text.Value
End If
Next
If ctrl = False Then
ligne = fin_liste + 1
ws_lame.Range("A" & ligne) = combo2.Value
fin_liste = text.Value
End If
End Sub

How to insert, through VBA, a formula in a cell with special characters like "-" or "$"?

I searched on internet, without any help coming out of that...
I simply would like to be able to have my VBA code to write this formula in a cell :
=IF(C4="-"; "-"; Cars!C4*C4*Data!$C$8)
As you guessed, there is a page called "Cars" and one called "Data" where I pick the informations needed.
Of course, as it is a VBA code, the C4 will be 2 variables, one for the C and one for the 4 that will evolve...
Actually, I tried this :
Worksheets("Calculation").Range(Column & PosStartCalc + 1).Formula = "=" & "IF(" & Column & PosStartCalc & " = " & "" - "" & ";" & " - " & ";" & "Cars!" & Column & PosStart & "*" & Column & PosStartCalc & "*" & "Data!" & "C" & "8" & ")"
(The variable Column contains the column letter and the variable PosStartCalc contains the row number)
This hurts my eyes and apparently VBA's ones too as it gives the error "Run-Time error '13': Type Mismatch'
Could anyone tell me how to do that?
Thanks in advance !
Try the following, assuming the column variable is a string and row a long variable. I might not have all the variables right, but you'll be able to get what I meant to do here.
Sub test()
Dim Col As String: Col = "C"
Dim Rw As Long: Rw = 4
With ThisWorkbook.Sheets("Calculation")
Debug.Print "=IF(" & Col & Rw & "=""-"",""-"",Cars!" & Col & Rw & "*" & Col & Rw & "*Data!$C$8)"
.Cells(Rw + 1, Col).Formula = "=IF(" & Col & Rw & "=""-"",""-"",Cars!" & Col & Rw & "*" & Col & Rw & "*Data!$C$8)"
End With
End Sub
So what you might forget easily is to use the , as parameter delimiter in a VBA programmed formula. When you put this on your sheet Excel will automatically replace that with the appropriate delimiter for your region.
Another thing to keep in mind; whenever you about to use a string value in such an function, don't forget to wrap it in double quotes!
Don't forget to remove the Debug.print .... line. It was merely there to show the output :)

Excel VBA For Loop writing Formula in cells depending on the number in the loop

I am trying to write a Forumla in cells (from cell A2 to AI, where I is the number in the For Loop).
The formula to be written must correspond to Cell M2 to MI, also where I is the number in the For Loop.
I am able to write the sheet-reference by itself:
ws.Cells(1 + I, KolonneForX + 1).Formula = " ='" & ws.Name & "'"
which gives me the formula ='Ark1' (by it self) in the cells i want.
And also the right name of cell to read:
ws.Cells(1 + I, KolonneForX + 2).Formula = "=CONCATENATE(""M"",TEXT(" & I & "+1,""0""))"
which gives me the formula MI (by it self, with the corresponing number for I) in the cells i want.
But when I try to put the two of them togheter, I can't get it to run and refer to the right cells.
This is the code I have been trying to run:
Sub OppretteKnutepunkt()
Dim ws As Worksheet
Set ws = Worksheets("Ark1")
Dim KolonneForX As Integer
For I = 1 To 5
ws.Cells(1 + I, KolonneForX + 2).Formula = "='" & ws.Name & "'!CONCATENATE(""M"",TEXT(" & I & "+1,""0""))"
Next I
End Sub
I want the Cell A2 to have the following formula:
='Ark1'!M2
I want the Cell A3 to have the following formula:
='Ark1'!M3
and so on.
Any suggestions?
You can achieve this without looping
Dim I as Long
I = 7
With ws.Range("A2:A" & I)
.Formula = "='" & .Parent.Name & "'!M2"
End With
With is a shorthand way of using the same prefix on a block of code. The VBA compiler prefixes everything that begins with a . with whatever is declared by the With block
The equivalent of the above would be:
ws.Range("A2:A" & I).Formula = "='" & ws.Range("A2:A" & I).Parent.Name & "'!M2"

Adding freshly created formula into new module

I've just created a brand new macro. Took function down below from internet (all credits goes to trumpexcel.com), code down below
Function CONCATENATEMULTIPLE(Ref As Range, Separator As String) As String
Dim Cell As Range
Dim Result As String
For Each Cell In Ref
Result = Result & Cell.Value & Separator
Next Cell
CONCATENATEMULTIPLE = Left(Result, Len(Result) - 1)
End Function
Then I proceed to extract data from various columns and into the one (my table is 20 rows x 10 columns)
Sub conact_data()
Dim i As Integer
For i = 2 To Cells(Rows.Count, "A").End(xlUp).Row
Cells(i, "M").Value = Cells(i, "A").Value & " " & _
Cells(i, "B").Value & " / " & Cells(i, "D").Value & "; "
Next i
End Sub
Thanks to that I've got combined data from column A, B and D, so its 20 rows. All I want to do now is to concatenate data from M2:M21 using CONCATENATEMULTIPLE function therefore I try various approach (I want this huge line in P2 cell) like :
Cells(2, 16).Value = CONCATENATEMULTIPLE (M2:M21, " ")
or
Range("P2") = "CONCATENATEMULTIPLE (M2:M21, " ")"
I don't really know how to apply that
Secondly, I'd like withdraw the Cells(i, "B").Value as percentage. Can I do that in one line like Cells(i, "B").NumberFormat="0.00%".Value (which is not working for me obviously) else I need to copy column B into another column with number format and then combine the new column, properly formatted instead of column B?
Thanks in advance
Percent format: Range("B" & i).NumberFormat = "0.00%"
CONCATENATEMULTIPLE
In VBA, CHR(32) = " "
In Excel, CHAR(32) = " "
With that being said...
'Value
Range("P2").Value = CONCATENATEMULTIPLE(Range("M2:M21"), CHR(32))
'Formula
Range("P2").Formula = "=CONCATENATEMULTIPLE(M2:M21, CHAR(32))"
You should really qualify all of your ranges with a worksheet
Say your workbook has 10 sheets. When you say Range("P2"), how do we (VBE) know what sheet you mean? Objects need to be properly qualified. Sometimes this is not a huge issue, but when you are working across multiple sheets, not qualifying ranges can lead to some unexpected results.
You can qualify with a worksheet a few ways.
Directly: ThisWorkbook.Sheets("Sheet1").Range("P2").Copy
Or use a variable like so
Dim ws as Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Range("P2").Copy
Now there is no room for ambiguity (potential errors) as to the exact location of Range("P2")
First of all, remove your ConcatenateMultiple() code, and instead use Excel worksheet function CONCAT(), which takes a range and a delimiter as parameters.
Here is how you can handle the percentage issue and supply a default for non-numeric items. I've also cleaned up the way you reference your data range.
Sub concat_data()
Dim rngRow As Range, vResult As Variant
Const DEFAULT = 0 'Can also be set to a text value, eg. "Missing"
For Each rngRow In [A2].CurrentRegion.Rows
If IsNumeric(rngRow.Cells(, 4)) Then vResult = rngRow.Cells(, 4) * 100 & "%" Else vResult = DEFAULT
Range("M" & rngRow.Row) = rngRow.Cells(, 1) & rngRow.Cells(, 2) & "/" & vResult & ";"
Next
[M2].End(xlDown).Offset(1).Formula = "=CONCAT(M2:M" & [M2].End(xlDown).Row & ",TRUE,"" "")"
End Sub
I'm not a fan of hard-coding range references, like the [A2] or Range("M"), but will leave that for another time.

Translate a worksheet formula in VBA

Can somebody help me to write this formula in excel VBA?
=IF(ISERROR(VLOOKUP(A3,Temp!$A$3:$A$595,1,FALSE)),A3,"0")
My code is getting stuck with :"syntax error"
Sub checkDuplitems()
Application.ScreenUpdating = False
Const top As Integer = 3
Dim bottom As Long
bottom = Sheets("Temp").Cells(Rows.Count, top).End(xlUp).row
With ThisWorkbook.Sheets("trash").Range("A" & top & ":A" & bottom)
.Formula = "=IF(ISERROR(VLOOKUP(A" & top & ",Temp!$B$" & top & ":$B$" & bottom & _
",1,FALSE)),A" & top & ", & '" 0" & ," '")"
.Value = .Value
.SortSpecial
End With
'Call something...
End Sub
You have a concatenation problem in the second line of the .Formula line.
To emulate the formula you have at the top of your question (which is wrong incidentally because you should be pointing to $B$3:$B$595 or something like that because your look up cell A3 should not be inside the VLOOKUP range).
Try this new .Formula line:-
.Formula = "=IF(ISERROR(VLOOKUP(A" & top & ",Temp!$B$" & top & ":$B$" & bottom & _
",1,FALSE)),A" & top & ", " & "0)"
Are you sure you want to use top as both the starting row in column A and the column to get the bottom row from the Temp worksheet? The important column on the Temp worksheet is column B (i.e. 2) not C (i.e. 3).
If you are putting formula(s) into Trash!A3:A595 that reference Trash!A3:A595 then these are circular references and cannot be resolved under normal conditions. I'll put the formulas into column Z.
If you are operating with Excel 2007 or newer then I would humbly propose this alternate that uses the worksheet's IFERROR function and does not attempt to make text out of the 0 returned value.
Const top As Integer = 3
Dim bottom As Long
bottom = Sheets("Temp").Cells(Rows.Count, "B").End(xlUp).Row '<~~change here
With ThisWorkbook.Sheets("trash")
With .Range("Z" & top, .Cells(Rows.Count, "A").End(xlUp).Offset(0, 25))
.Formula = "=IFERROR(VLOOKUP(A" & top & ", Temp!$B$" & top & ":$B$" & bottom & _
", 1, FALSE), 0)" '<~~ big change here
.Value = .Value
End With
End With
It is also curious as to why the number of rows of formulas in the Trash worksheet must be governed by the number of rows of data in the Temp worksheet. I would have thought that the number of values in column A of the Trash sheet should govern how many formulas go into the Trash worksheet.

Resources