Right now, I have a code that will generate a name for a folder in a network drive. Once the user types in the name for the new folder in a prompt box, I am trying to add the name into two places: the bottom of a list in a column, and to the end of the list in the first row (the first empty cell in the row)
Currently, my code to put the name at the bottom of the list in column D works:
lMaxRows = Cells(Rows.Count, "D").End(xlUp).Row
Range("D" & lMaxRows + 1) = accountname
where "accountname" is the input that the prompt asks for. Then the code goes to the last cell that was used in the column, goes one additional cell, and fills it with the "accountname".
Is there a way to convert this code to work for a list in a row? I'm trying to build the list from left to right starting in column X of row 1. This is what I have right now, but it's not working and I'm not sure if it's a language issue or something more.
lMaxCol = Cells(1, Columns.Count).End(xlToRight).Column
Range("X1" & lMaxCol + 1) = accountname
Any ideas? Is this a quick fix or will it require a more sophistacted code?
-AC
lMaxCol = Cells(1, Columns.Count).End(xlToRight).Offset(0,1).Column
If lMaxCol<26 Then lMaxCol=26
Cells(1, lMaxCol) = accountname
Dim lMaxCol As Long
With ActiveSheet.Rows(1) 'might want a different sheet
lMaxCol = .Find(what:="", after:=[w1], LookIn:=xlValues, searchdirection:=xlNext).Column
End With
Cells(1, lMaxCol) = AccountName
Note that this should, indeed, find the first empty cell at or after X1. If there is, for example, data in X1 and AA1, the above will return 25, not 28. If this might be an issue, and you prefer to return 28 in that case, you could use something like:
Dim lMaxCol As Long
With ActiveSheet.Range("x1", Cells(1, Columns.Count))
On Error Resume Next
lMaxCol = .Find(what:="*", after:=.Cells(1, .Columns.Count), LookIn:=xlValues, _
searchdirection:=xlPrevious).Column + 1
If Err.Number <> 0 Then lMaxCol = 24
On Error GoTo 0
End With
Cells(1, lMaxCol) = AccountName
If you don't need to know lMaxCol for some other part of the code, this code can be simplified.
Dim C As Range
With ActiveSheet.Range("x1", Cells(1, Columns.Count))
Set C = .Find(what:="*", after:=.Cells(1, .Columns.Count), LookIn:=xlValues, _
searchdirection:=xlPrevious)
If Not C Is Nothing Then
C.Offset(0, 1) = AccountName
Else
Cells(1, 24) = AccountName
End If
End With
Related
I hope your weeks are going well.
Currently writing a data entry from in a VBA user form,
It will be using an array of checkboxes to select size which then fills a row with the other data provided when that checkbox is ticked.
I'm currently running into an issue where I don't know what code to run to have the function delete its previous data when the checkbox is unticked.
Private Sub CheckBox0k_Click()
'''Input
Dim ws As Worksheet
Dim LastRow As Long, RowInsert As Long
Set ws = ThisWorkbook.Worksheets("stock")
With ws
LastRow = .Cells(Rows.Count, "A").End(xlUp).row
RowInsert = .Range("A1:A" & LastRow).Find("*", .Cells(LastRow, "A"), xlValues, , , xlPrevious).row
RowInsert = RowInsert + 1
'add the uk size input code here
'''Checkbox based search
''Start
If Me.CheckBox0k.Value = True Then
''''This has to match the number of rows input below
.Cells(RowInsert, "A").Resize(1, 8).Value = Array( _
Me.txtDate.Text, _
Me.textboxparentsku.Text, _
Me.textboxsku.Text, _
Me.comboboxbrand.Text, _
Me.comboboxclosure.Text, _
Me.comboboxgender.Text, _
Me.comboboxmaterial.Text, _
Me.comboboxmodel.Text _
)
ws.Range("I" & RowInsert).Value = CheckBox0k.Caption
'This is the code I'm having issues with
ElseIf CheckBox0k.Value = False Then
.Cells(RowInsert, "A").Resize(1, 8).Value = ws.Range("I" & RowInsert).Value = ""
End If
''Finish
Set ws = Nothing
End With
End Sub
A picture of the current UI with the multiple checkboxes
In order to help, we would need to know more about the process. I men, do you need clearing the last 8 entries (columns)? If so, the working solution should be something like
.Cells(RowInsert, "A").Resize(1, - 9).Value = ""
But your code must check if there are data in the first columns of the row to be processed and warn...
Ok I have sorted it I made a new rule called RowInvert = RowInsert - 1 and put that into FaneDuru's code:
ElseIf Me.CheckBox0k.Value = False Then .Cells(RowInvert, "A").Resize(1, 9).Value = ""
This is my first time using VBA and macros in excel, or excel really for that matter. I appreciate any help or insight that you could give me, ranging from what functions to loops can help me succeed in this task
I am trying to get this workbook set up from this:
Sample Work Book
I get a list that has to be reordered in order to import into another system. My task list is as follows for a macro:
Names and companies have to be merged into one, if there is a different name of a person, that must be concatenated. There will not be two different companies per company header.
Every File ID per company must be concatenated
Individual fees must be replaced with total fee per company.
Sorted by internal ID #, A-Z
Only one header on the new sheet
To look like this:
Target Work Book
My code below runs this: Current Progress
Sub format()
Application.ScreenUpdating = False
'This is the setup to get rid of unnecessary cells'
Dim rCell As Range
Dim cRow As Long, LastRow As Long
LastRow = Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
'''Delete Merged Cells'''
With Worksheets("Sheet1").Range("A1", Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp))
Do
Set c = .Find(What:="*Company Name:*", After:=[A1], LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not c Is Nothing Then
cRow = c.Row
c.EntireRow.Delete
End If
Loop While Not c Is Nothing And cRow < LastRow
End With
'''Delete Headings'''
With Worksheets("Sheet1").Range("A1", Worksheets("Sheet1").Range("B" & Rows.Count).End(xlUp))
Do
Set c = .Find(What:="*File #*", After:=[A1], LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not c Is Nothing Then
cRow = c.Row
c.EntireRow.Delete
End If
Loop While Not c Is Nothing And cRow < LastRow
End With
''' Delete Sub Total"""
With Worksheets("Sheet1").Range("A1", Worksheets("Sheet1").Range("B" & Rows.Count).End(xlUp))
Do
Set c = .Find(What:="*Sub Total:*", After:=[A1], LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not c Is Nothing Then
cRow = c.Row
c.EntireRow.Delete
End If
Loop While Not c Is Nothing And cRow < LastRow
End With
End Sub
Again, I appreciate any help on this matter. Thank you!
There are a lot of ways to loop through the cells.
I picked column D with the company name as it didn't have too much clutter.
It's usually good to find the last row, to not loop through cells that we don't need. THere is a lot of ways for doing so as well. Today we'll go with Range("D" & .Rows.Count).End(xlUp).Row.
For the loop, we can use the For next approach, example:
For i = 1 To Sheets(1).Range("A" & Sheets(1).Rows.Count).End(xlUp).Row
If Not Cells(i, 4).Value = "" Then
Next i
But this time, I went with the For Each, because I think it's a bit more readable.
Sub groupingEach()
Dim entry As Variant, prev As String, lRow As Long, lRow2 As Long
Dim inSht As Worksheet, outSht As Worksheet
Set inSht = Sheets(1)
Set outSht = Sheets(2)
lRow = inSht.Range("D" & inSht.Rows.Count).End(xlUp).Row 'last row
For Each entry In inSht.Range("D1:D" & lRow) 'loop 1st sheet
lRow2 = outSht.Range("D" & outSht.Rows.Count).End(xlUp).Row 'last row in output
If entry = prev And Not entry = "" Then
'-Group'
If InStr(outSht.Cells(lRow2, 3), entry.Offset(, 1)) = 0 Then 'does name exist?
outSht.Cells(lRow2, 3) = outSht.Cells(lRow2, 3) & vbNewLine & entry.Offset(, 1)
End If
outSht.Cells(lRow2, 5) = outSht.Cells(lRow2, 5) & vbNewLine & entry.Offset(, -2)
outSht.Cells(lRow2, 6) = outSht.Cells(lRow2, 6) + entry.Offset(, 2)
ElseIf Not entry = prev And Not entry = "" And Not entry = "Company" Then
'-New row
prev = entry 'Save company name for comparison
outSht.Cells(lRow2 + 1, 1) = entry.Offset(, -3)
outSht.Cells(lRow2 + 1, 2) = "Payable" 'Where to get this value?
outSht.Cells(lRow2 + 1, 3) = entry.Offset(, 1)
outSht.Cells(lRow2 + 1, 4) = entry
outSht.Cells(lRow2 + 1, 5) = entry.Offset(, -2)
outSht.Cells(lRow2 + 1, 6) = entry.Offset(, 2)
End If
Next entry
outSht.Cells(lRow2 + 3, 1).Value = "Grand Total:"
outSht.Cells(lRow2 + 3, 2).Formula = "=SUM(F:F)"
End Sub
From the examples, this should handle the document all the way from the Sample to the target. I wanted to loop the value copying, but the change in column order made it annoying.
I have wrote a programm to replace special character in cell with normal character(alphabets)
I have written comments for each block in my programm.
However before executing all rows, after second row it goes to next column
Sub special_char_Replace()
Dim h As String
Dim m, clm, rw As Integer
Dim colspc As New Collection
Dim valspc As New Collection
'Below part makes collection of special character and its replacement values
On Error Resume Next
ThisWorkbook.Worksheets("Sheet2").Activate
m = Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To m
colspc.Add Cells(i, 1)
valspc.Add Cells(i, 2)
Next
'Activate destination workbook from which special characters to be replaced
Workbooks("common file.xlsx").Worksheets("Sheet1").Activate
LR = Cells(Rows.Count, "E").End(xlUp).Row
'Below loop replaces special characters and inserts original value at 5th 'column aside
For clm = 5 To 6
For rw = 2 To LR
For i = 1 To m
On Error Resume Next
h = Range(Cells(rw, clm), Cells(rw, clm)).Find(What:=colspc(i), after:=Range(Cells(rw, clm), Cells(rw, clm)), LookIn:=xlFormulas, Lookat:=xlPart).Address
If h <> "" Then
Range(h).Offset(0, 5) = Range(h).Value
Range(Cells(rw, clm), Cells(rw, clm)).Replace What:=colspc(i), replacement:=valspc(i), Lookat:=xlPart, searchorder:=xlByColumns, MatchCase:=False
End If
h = ""
Next i
Next rw
Next clm
End Sub
Thanks for everyone's support
I made changes, instead of find function, I have defined two dimentional string cellval(I,J)
First I will save all cell values in this string with for loop
cellval(I, j) = Cells(I, j).Value
After execution of replace command, below lines will check all string values with result
if there is changes it will relfect in output sheet
If cellval(I, j) <> Sheets(ws.Name).Cells(I, j).Value Then
Cells(I, j).Value = cellval(I, j)
I have a excel sheet like at below. I want to find some strings in my excel's third cell. The string is 180 days. When the cell value includes 180 days, I want write previous cells value in next to empty cells like in below picture. I want to write process plan in first cell, operation title in second cell. I wrote this codes but it's not working like what I want.
Sub Button1_Click()
Dim excelRange As Long
Dim i As Long
Dim k As Long
'Dim txt As String
excelRange = ActiveSheet.Cells(1048576, 3).End(xlUp).Row
k = 2
For a = 2 To excelRange
txt = Cells(a, 3)
k = a
If InStr(1, txt, "180 days") > 0 Then
For i = a To 2 Step -1
txt1 = Cells(i, 3)
If InStr(1, txt1, "Oper Title") > 0 Then
Cells(a, 2) = Cells((k + 1), 3)
ElseIf InStr(1, txt1, "Process") > 0 Then
Cells(a, 1) = Cells(k, 3)
Else:
k = k - 1
End If
Next i
End If
Next a
End Sub
Sub test()
Dim excelRange As Range
Dim criteriRange As Range
Dim evaluateRange As Range
Dim c As Range
Dim i As Long
Set excelRange = Range("C1:C" & Cells(1048576, 3).End(xlUp).Row)
For Each cell In excelRange
If UCase(cell.Text) Like "*180 DAY*" Then
If criteriRange Is Nothing Then
Set criteriRange = cell
Else
Set criteriRange = Union(criteriRange, cell)
End If
End If
Next
If Not criteriRange Is Nothing Then
For Each c In criteriRange
For i = c.Row To 1 Step -1
If UCase(Cells(i, 3)) Like "*PROCESS PLAN*" Then
c.Offset(0, -2) = Cells(i, 3)
Exit For
End If
Next
For i = c.Row To 1 Step -1
If UCase(Cells(i, 3)) Like "*OPER TITLE*" Then
c.Offset(0, -1) = Cells(i + 1, 3)
Exit For
End If
Next
Next
End If
End Sub
Instead of looping through a range, your macro will run much faster if you use the Range.Find method.
In your code, you did not check to ensure that all of your sets of Process | Title | 180 Days are complete. I added that to the code below, by making sure that the Process and Title rows were found after the previous 180 day row (or before the 180 day row for the first instance).
In your code, you did not check to see if the cells where you want to output this information are, in fact, empty. If you really want to do that, you can easily modify this code to check these cells before writing to them.
Hopefully, through the comments and the use of meaningful variable names, you will be able to understand what is going on. But you might want to also read through VBA Help for the Range.Find method.
In general, we search down to find the 180 day row, then search up from there to find the associated Process and Title rows.
If a preceding Process or Title row should be before the preceding 180 day row, then we have an incomplete set, output the error message, and terminate the procedure.
If necessary, you could develop procedures to deal with incomplete data sets.
Option Explicit
Sub Info()
Dim searchRng As Range, C As Range, cProcessPlan As Range, cOperTitle As Range
Dim firstAddress As String 'to check when we are done
Dim lastAddress As String 'to check for incomplete data sets
'Where are we looking?
Set searchRng = ThisWorkbook.Worksheets("Sheet1").Columns(3)
With searchRng
Set C = .Find(what:="180 Days", after:=.Cells(1, 1), LookIn:=xlValues, _
lookat:=xlPart, searchorder:=xlByRows, _
searchdirection:=xlNext, MatchCase:=False)
If Not C Is Nothing Then
firstAddress = C.Address
lastAddress = C.Address
Set cOperTitle = .Find(what:="Oper Title", after:=C, searchdirection:=xlPrevious)
Set cProcessPlan = .Find(what:="Process Plan", after:=C, searchdirection:=xlPrevious)
If Not cOperTitle Is Nothing Or Not cProcessPlan Is Nothing Then
'check for full set
If cOperTitle.Row > Range(lastAddress).Row Or cProcessPlan.Row > Range(lastAddress).Row Then
MsgBox "Incomplete Data Set" & vbLf & "Before: " & C.Address
Exit Sub
End If
C.Offset(0, -1) = cOperTitle.Offset(1, 0)
C.Offset(0, -2) = cProcessPlan
Else
MsgBox "Title or Process Plan not found"
Exit Sub
End If
Do
Set C = .Find(what:="180 Days", after:=C, LookIn:=xlValues, _
lookat:=xlPart, searchorder:=xlByRows, _
searchdirection:=xlNext, MatchCase:=False)
If C.Address = firstAddress Then Exit Do
Set cOperTitle = .Find(what:="Oper Title", after:=C, searchdirection:=xlPrevious)
Set cProcessPlan = .Find(what:="Process Plan", after:=C, searchdirection:=xlPrevious)
'check for a full set
If cOperTitle.Row < Range(lastAddress).Row Or cProcessPlan.Row < Range(lastAddress).Row Then
MsgBox "Incomplete Data Set" & vbLf & "Between: " & lastAddress & " and " & C.Address
Exit Sub
End If
C.Offset(0, -1) = cOperTitle.Offset(1, 0)
C.Offset(0, -2) = cProcessPlan
lastAddress = C.Address
Loop
End If
End With
'next stuff
End Sub
Using a variant array is fast.
Sub test()
Dim Ws As Worksheet
Dim rngDB As Range
Dim vDB As Variant
Dim vRow(), vTitle(), vProcess()
Dim i As Long, j As Long, k As Long, m As Long
Set Ws = ActiveSheet
With Ws
Set rngDB = .Range("a1", .Range("c" & Rows.Count).End(xlUp))
End With
vDB = rngDB
For i = 1 To UBound(vDB, 1)
If InStr(vDB(i, 3), "180 days") Then
j = j + 1
ReDim Preserve vRow(1 To j)
vRow(j) = i
ElseIf InStr(vDB(i, 3), "Oper Title") Then
k = k + 1
ReDim Preserve vTitle(1 To k)
vTitle(k) = vDB(i + 1, 3)
ElseIf InStr(vDB(i, 3), "Process") Then
m = m + 1
ReDim Preserve vProcess(1 To m)
vProcess(m) = vDB(i, 3)
End If
Next i
For i = 1 To j
vDB(vRow(i), 1) = vProcess(i)
vDB(vRow(i), 2) = vTitle(i)
Next i
rngDB = vDB
End Sub
here is the code im trying:
Set found = Worksheets("Result").Range("A:A").Find(Prefix, , xlValues, xlWhole)
found.Offset(0, 1).Value = CInt(found.Offset(0, 1).Value) + CInt(C.Offset(0, 1).Value)
Prefix is a 3 digit number that is found in a column, what i then want to do is increase the cell to the right of where it is found by a cell one to the right of "C". I am getting a type mismatch error.
here is where c comes from:
For Each C In Worksheets("AMZ").Range("C2:C" & endRow).Cells
any ideas?
EDIT: Full code
Sub processData()
Dim endRow As Variant
endRow = Worksheets("AMZ").Range("A65536").End(xlUp).Row
For Each C In Worksheets("AMZ").Range("C2:C" & endRow).Cells
Dim found As Range
Prefix = C.Value
C.Select
'remove prefix
If Not Left(Prefix, 3) = "FBA" Then
'nothing
If Mid(Prefix, 3, 1) = "-" Then
Prefix = Left(Prefix, 2)
ElseIf Mid(Prefix, 4, 1) = "-" Then
Prefix = Left(Prefix, 3)
Else
Prefix = "-1"
End If
If Not Prefix = "-1" Then
Set found = Worksheets("Result").Range("A:A").Find(Prefix, , xlValues, xlWhole)
found.Offset(0, 1).Value = CInt(Val(found.Offset(0, 1).Value)) + CInt(Val(C.Offset(0, 1).Value))
End If
End If
Next
End Sub
If found.Offset(0, 1).Value) or CInt(C.Offset(0, 1).Value) are string values, like "" or "1234hello" or anything that does not directly translate to an integer, you get the error you listed.
The easiest way to correct this, is to surround the value with the Val(string) function.
In your circumstance, you would use the following
found.Offset(0, 1).Value = CInt(Val(found.Offset(0, 1).Value)) + CInt(Val(C.Offset(0, 1).Value))
A note about Val, if the values you provide could not possibly be a number, it will default to 0. Otherwise it will take any numbers at the beginning of the string offered. For more about Val read the link. (same as above)