I'm working on a project where I have sales data broken down into quarters. What I need to do is in front of each column insert the three months that belong in that quarter. I started with a select case statement, but then realized that probably isn't the best way to do it. What I want to do is have it be a variable range (there can be anything from 1-10 years pasted in) so I set it up to search InStr for "Q1", "Q2" and then insert the rows and proper month titles. I haven't inserted month titles yet, because I want to get the rows inserted first, but if you have a suggestion on how to do that without specifying cell values that'd also be awesome! it's also worth mentioning this data insertion starts on column U and will every time. Thanks for any help or suggestions!
Sub InsertMonths()
If cell.value = InStr(1, cell, "Q1", 1) Then
Dim y As String
y = InStr(1, cell, "Q1", 1)
If y = "" Then Exit Sub
Dim x As Long
For x = Cells(Columns.Count, 1).End(xlUp).Column To 1 Step -1
If Cells(x, 18).value = y Then
Columns(x + 3).Resize(1).Insert
End If
Next x
Else cell.value = InStr(1, cell, "Q2", 1) Then
Dim y As String
y = InStr(1, cell, "Q2", 1)
If y = "" Then Exit Sub
Dim x As Long
For x = Cells(Columns.Count, 1).End(xlUp).Column To 1 Step -1
If Cells(x, 18).value = y Then
Columns(x + 3).Resize(1).Insert
End If
Next x
Else InStr(1, cell, "Q3", 1) then
Dim y As String
y = InStr(1, cell, "Q3", 1)
If y = "" Then Exit Sub
Dim x As Long
For x = Cells(Columns.Count, 1).End(xlUp).Column To 1 Step -1
If Cells(x, 18).value = y Then
Columns(x + 3).Resize(1).Insert
End If
Next x
Else InStr(1, cell, "Q4", 1) then
Dim y As String
y = InStr(1, cell, "Q4", 1)
If y = "" Then Exit Sub
Dim x As Long
For x = Cells(Columns.Count, 1).End(xlUp).Column To 1 Step -1
If Cells(x, 18).value = y Then
Columns(x + 3).Resize(1).Insert
End If
Next x
End If
End Sub
Without coming into too much detail in the exact situation, here you have a couple of loops doing the same than your set of conditions. It is prepared to deal with as many cells as required (letters and ints).
Sub InsertMonths()
Dim startInt, endInt, totLetters, lettersCount, curInt As Integer
Dim allLetters(10), curLetter, curCell As String
totLetters = 1
allLetters(1) = "Q"
startInt = 1
endInt = 4
lettersCount = 0
Do
lettersCount = lettersCount + 1
curLetter = allLetters(lettersCount)
curInt = startInt - 1
Do
curInt = curInt + 1
curCell = curLetter & CStr(curInt)
If cell.Value = InStr(1, cell, curCell, 1) Then
Dim y As String
y = InStr(1, cell, curCell, 1)
If y = "" Then Exit Sub
Dim x As Long
For x = Cells(Columns.Count, 1).End(xlUp).Column To 1 Step -1
If Cells(x, 18).Value = y Then
Columns(x + 3).Resize(1).Insert
End If
Next x
End If
Loop While (curInt < endInt)
Loop While (curLetter < totLetters)
End Sub
In your code, where you are setting the value in the cell to hold the month, put the following formula instead of the value
Cells(x, y).value = "=(MID($D2,2,1) - 1) * 3 + 1"
Second column would be
Cells(x, y).value = "=(MID($D2,2,1) - 1) * 3 + 2"
And third would be
Cells(x, y).value = "=(MID($D2,2,1) - 1) * 3 + 3"
In all of the cases above, the $D2 should reference the cell you found to contain the "Q#". The formulas are basically taking the numerical part of the quarter and calculating the 1st, 2nd and 3rd months of the quarter.
Also note that this gives you the month number. If you want the name, you should be able to figure that out.
Related
I'm having trouble with my loop not running throughout my entire sheet 1. If the value in Sheet 1 "tests" exist in sheet 2 "cancer". Then i want the value in sheet 2 "cancer" to be placed into sheet 1 "Tests". The code works except for the loop. Currently it only applies to the first record in my first sheet then stops.
Sub Testing()
Dim x As Long
Dim y As Long
x = 2
y = 2
Do While Sheets("Cancer").Cells(y, 1).Value <> ""
If LCase(Trim(Sheets("Cancer").Cells(y, 1).Text)) = LCase(Trim(Sheets("Tests").Cells(x, 3).Text)) Then
If Sheets("Tests").Cells(x, 4).Value = "" Then
Cells(x, 4) = (Trim(Sheets("Cancer").Cells(y, 3).Text))
x = x + 1
End If
End If
y = y + 1
Loop
End Sub
I would use two for loops
for y = 2 to 10000 'the range your values are found
if Sheets("Cancer").Cells(y, 1).Value <> "" then
for x = 2 to 10000 'the range your values are in
If LCase(Trim(Sheets("Cancer").Cells(y, 1).Text)) = LCase(Trim(Sheets("Tests").Cells(x, 3).Text)) and Sheets("Tests").Cells(x, 4).Value = "" Then
Cells(x, 4) = (Trim(Sheets("Cancer").Cells(y, 3).Text))
End If
next
end if
next
The reason for the loop not running throughout the entire sheet 1 is because of these two lines:
If LCase(Trim(Sheets("Cancer").Cells(y, 1).Text)) = LCase(Trim(Sheets("Tests").Cells(x, 3).Text)) and Sheets("Tests").Cells(x, 4).Value = ""
If these conditionals aren't both true, then x will never loop to its next iteration, and you'll have gone through looping through each value of Sheet2 "Cancer" while checking only the same record of Sheet1 "Tests".
You've almost qualified all of your ranges. You missed one. Try changing the line:
Cells(x, 4) = (Trim(Sheets("Cancer").Cells(y, 3).Text))
to
Sheets("Tests").Cells(x, 4) = (Trim(Sheets("Cancer").Cells(y, 3).Text))
New to VBA if someone could help me what im doing wrong here.
Trying to run a loop such that it looks for a specific text, starts the loop then stops at a specific point.
The loops is such that I want it to copy some values below in my sheet hence a is 55.
Im facing the error Block IF without End If
Here is the code:
Private Sub CommandButton3_Click()
For y = 1 To 15 Step 5
Dim x As Double
Dim a As Double
x = 1
a = 55
If Cells(x, y).Value = "Text1" Then
Do Until Cells(x, y).Value = "Text2"
Cells(a, y) = Cells(x, y).Value
Cells(a, y + 1) = Cells(x, y + 1)
x = x + 1
a = a + 1
Loop
End Sub
Indenting is the way forward, you have a for statement with no next and an if with no End If:
Private Sub CommandButton3_Click()
For y = 1 To 15 Step 5
Dim x As Double
Dim a As Double
x = 1
a = 55
If Cells(x, y).Value = "Text1" Then
Do Until Cells(x, y).Value = "Text2"
Cells(a, y) = Cells(x, y).Value
Cells(a, y + 1) = Cells(x, y + 1)
x = x + 1
a = a + 1
Loop
End If
Next y
end sub
Besides the issues I mentioned in the comments to your post, if I understood you correctly, you want to loop on cells at Column A, find the first "Text1", then copy all the cells to row 55 and below, until you find "Text2". If that's the case, try the code below :
Private Sub CommandButton3_Click()
Dim x As Long, y As Long
Dim a As Long
Dim LastRow As Long
With Worksheets("Sheet1") '<-- modify "Sheet1" to your sheet's name
For y = 1 To 15 Step 5
x = 1 '<-- reset x and a (rows) inside the columns loop
a = 55 '<-- start pasting from row 55
LastRow = .Cells(.Rows.Count, y).End(xlUp).Row
While x <= LastRow '<-- loop until last row with data in Column y
If .Cells(x, y).Value Like "Text1" Then
Do Until .Cells(x, y).Value = "Text2"
.Cells(a, y).Value = .Cells(x, y).Value
.Cells(a, y + 1).Value = .Cells(x, y + 1).Value
x = x + 1
a = a + 1
Loop
End If
x = x + 1
Wend
Next y
End With
End Sub
Cant seem to figure out why my code is not showing output. New VBA programmer only know basics so any help would be helpful.
What I want is for Excel to start checking a specific column for a specific text1 and then start copying and pasting those values till it reaches text2. After that I want it to check the next fifth column in the same manner.
If you could suggest modifications to my code.
Without putting in a for loop for the column my code looks like this.
Private Sub CommandButton7_Click()
Dim x As Long, y As Long
Dim a As Long
y = 1 'starts with the first column
x = 1 'first row
a = 70 'this is the row where i want the data to be posted
If Cells(x, y).Value = "text1" Then 'check first for specific text
Do Until Cells(x, y).Value = "text2" 'stop here
Cells(a, y).Value = Cells(x, y).Value 'copy that data to new row
Cells(a, y + 1).Value = Cells(x, y + 1).Value 'and the column adjacent to it
x = x + 1
a = a + 1
Loop
Else
x = x + 1 'if not on that row then check the next row
End If
End Sub
Really hard to see what is going wrong here as your code should be doing what you want.
The only other thing that could throw your results is when you have different case ,as VBA will treat a string with an upper case character as being different, so you may not actually be entering the loop at all. And I am assuming that text1 is just a sample string for the question.
So comparing the string in lower case will ensure that if you have any upper case characters they will be compared correctly, using the LCase function should help with that.
Full code,
Private Sub CommandButton7_Click()
Dim x As Long, y As Long
Dim a As Long
y = 1 'starts with the first column
x = 1 'first row
a = 70 'this is the row where i want the data to be posted
If LCase(Cells(x, y).Value) = LCase("text1") Then 'check first for specific text
Do Until LCase(Cells(x, y).Value) = LCase("text2") 'stop here
Cells(a, y).Value = Cells(x, y).Value 'copy that data to new row
Cells(a, y + 1).Value = Cells(x, y + 1).Value 'and the column adjacent to it
x = x + 1
a = a + 1
Loop
Else: x = x + 1 'if not on that row then check the next row
End If
End Sub
Kind of hard to see the big picture but I think I produced the result you want with:
Sub FindText()
Dim textFound As Range
Dim x As Long, y As Long
Dim a As Long
y = 1 'starts with the first column
x = 0 'first row
a = 70 'this is the row where i want the data to be posted
Set textFound = ActiveSheet.Columns(y).Cells.Find("Text1")
Do Until textFound.Offset(x, 0).Value = "Text2"
Cells(a + x, y).Value = textFound.Offset(x, 0).Value
Cells(a + x, y + 1).Value = textFound.Offset(x, 1).Value
x = x + 1
Loop
End Sub
This code is far from perfect but should work in most circumstances.
My problem is the as follows:
I have 3 columns and 20 rows, that contains numbers.
There is a line with numbers between 1 to 20 in order crescente, the other cells contains bigger numbers then 100 or whatever.
My homework is that I have to write a VBA code which fill color the cells that contains the line. This way i going to have a "colorful snake" from the cells that contains the numbers between 1 to 20.
Of course, the starting number cell is "A1"
the ending cell can be anywhere in the area "A1:C20"
the substance is the colored cells must have follow the numbers in order cresence!
Sub MeykEhYewowSnakhey()
Dim r, c
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
For r = 1 To ws.UsedRange.Rows.Count
For c = 1 To ws.UsedRange.Columns.Count
If ws.Cells(r, c).Value < 100 Then
ws.Cells(r, c).Interior.ColorIndex = 6
End If
Next
Next
End Sub
Try that.
There is probably a much more efficient way to solve this but this is my solution.
Sub Snake()
Dim wbk As Workbook
Dim ws As Worksheet
Dim mySnake As Integer, x As Integer, y As Integer
Set wbk = Workbooks("Book1.xlsm")
Set ws = wbk.Worksheets("Sheet1")
x = 1
y = 1
With ws
For mySnake = 1 To 20
If .Cells(x, y) = mySnake Then
.Cells(x, y).Interior.Color = vbYellow
'Check cell below
If .Cells(x + 1, y) = mySnake + 1 Then
x = x + 1
'Check cell to right
ElseIf .Cells(x, y + 1) = mySnake + 1 Then
y = y + 1
'Check cells to left if y <> 1
ElseIf y <> 1 Then
If .Cells(x, y - 1) = mySnake + 1 Then
y = y - 1
End If
'Check cells above if x <> 1
ElseIf x <> 1 Then
If .Cells(x - 1, y) = mySnake + 1 Then
x = x - 1
End If
End If
End If
Next mySnake
End With
End Sub
I am trying to write a macro which search data from one sheet and copy's to another.
But now I have a problem because I want to copy data between two searches and paste the whole data from multiple cells into one single cell.
For example in the above picture my macro:
SEARCH for "--------------" and "*****END OF RECORD"
COPIES everything in between , here example data in row 29 and 30 and from column A,B,C
PASTE all the data from multiple cells A29,B29,C29 and then A30,B30,C30 to single cell in sheet 2 say cell E2.
This pattern is reoccurring in the column A so I want to search for the next occurrence and do all the steps 1,2,3 and this time I will paste it in Sheet2 , cell E3.
Below is the code:
I am able to search my pattern but hard time in giving references to the cells in between those searched patterns and then copying all the data to ONE cell.
x = 2: y = 2: Z = 7000: m = 0: n = 0
Do
x = x + 1
If ThisWorkbook.Sheets("lic").Range("A" & x) = "---------------------" Then m = x
If ThisWorkbook.Sheets("lic").Range("A" & x) = "****** END OF RECORD" Then n = x
If (n > 0) Then
Do
For i = m To n
ThisWorkbook.Sheets("lic").Range("A" & i + 1).Copy
ThisWorkbook.Sheets("lic").Range("B" & i + 1).Copy
ThisWorkbook.Sheets("lic").Range("C" & i + 1).Copy
'If (n > 0) Then ThisWorkbook.Sheets("Sheet1").Range("E" & y) = ThisWorkbook.Sheets("lic").Range("A" & m + 1, "C" & n - 1): y = y + 1
'If (n > 0) Then ThisWorkbook.Sheets("Sheet1").Range("E" & y).Resize(CopyFrom.Rows.Count).Value = CopyFrom.Value: y = y + 1
Loop While Not x > Z
'Driver's Licence #:Driver's Licence #:Driver's Licence #:
x = 2: y = 2: Z = 7000: counter = 1
Do
x = x + 1
If ThisWorkbook.Sheets("lic").Range("A" & x) = "Driver's Licence #:" Then counter = counter + 1
If (counter = 2) Then ThisWorkbook.Sheets("Sheet1").Range("B" & y) = ThisWorkbook.Sheets("lic").Range("C" & x): y = y + 1: counter = 0
If x = Z Then Exit Sub
Loop
End Sub
Considering that the search is working correctly, about the copy thing you just need to do:
Sheet2.Range("E2").value = ThisWorkbook.Sheets("lic").Range("A" & i + 1).value & ";" & ThisWorkbook.Sheets("lic").Range("B" & i + 1).value & ";" & ThisWorkbook.Sheets("lic").Range("C" & i + 1).value
The result will be something like: AIR COO; L DAT; A
--------UPDATE---------
It was hard to understand your code, so I'm write a new one. Basically it's copy what it found on sheet1 to sheet2.
Sub Copy()
Dim count As Integer 'Counter of loops to the for
Dim Z As Integer 'Limit of (?)
Dim h As Integer 'Count the filled cells on sheet2
Dim y As Integer 'Counter the columns to be copied
Z = 7000
h = 1
'Assuming that the "----" will always be on the top, the code will start searching on the second row
'if it's not true, will be needed to validate this to.
For count = 2 To Z
If Sheet1.Cells(count, 1).Value <> "****** END OF RECORD" Then
If Sheet1.Cells(count, 1).Value <> "" Then
For y = 1 To 3 'In case you need to copy more columns just adjust this for.
Sheet2.Cells(h, 1).Value = Sheet2.Cells(h, 1).Value & Sheet1.Cells(count, y).Value
Next y
h = h + 1
End If
Else
MsgBox "END OF RECORD REACHED"
Exit Sub
End If
Next count
End Sub
Maybe I don't get the full idea but this might work for you.
I'm not at all sure what you want to see in the final output, so this is an educated guess:
Sub DenseCopyPasteFill ()
Dim wsFrom, wsTo As Worksheet
Dim ur As Range
Dim row, newRow As Integer
Dim dataOn As Boolean
Dim currentVal As String
dataOn = False
newRow = 3
Set wsFrom = Sheets("Sheet1")
Set wsTo = Sheets("Sheet2")
Set ur = wsFrom.UsedRange
For row = 1 To ur.Rows.Count
If wsFrom.Cells(row, 1).Value2 = "--------------" Then
dataOn = True
ElseIf wsFrom.Cells(row, 1).Value2 = "***** END OF RECORD" Then
newRow = newRow + 1
dataOn = False
ElseIf dataOn Then
currentVal = wsTo.Cells(newRow, 5).Value2
wsTo.Cells(newRow, 5).Value2 = currentVal & _
wsFrom.Cells(row, 1) & wsFrom.Cells(row, 2) & _
wsFrom.Cells(row, 3)
End If
Next row
End Sub
If you can get away without using the Windows clipboard, I would. Instead of copy/paste, here I demonstrated how you can simply add or append a value.
Add this sub:
Sub copy_range(rng As Range)
Dim str As String
str = rng.Cells(1).Value & rng.Cells(2).Value & rng.Cells(3).Value
Range("E" & Range("E" & Rows.Count).End(xlUp).Row + 1).Value = str
End Sub
Then your for loop should look like this:
For i = m To n
copy_range ThisWorkbook.Sheets("lic").Range("A" & i + 1 & ":C" & i + 1)
Next i