I have simple problem, but I am not able to find a "fix" for it.
I have the following code:
cmdSQLData.CommandText = Query 'some select
cmdSQLData.CommandType = adCmdText
cmdSQLData.CommandTimeout = 0
Set rs = cmdSQLData.Execute()
j = 1
x = 6 'the line I want the data to start
rs.MoveFirst
Do Until rs.EOF
Sheet1.Range("A" & x).Value = rs![name1]
Sheet1.Range("B" & x).Value = rs![name2]
Sheet1.Range("C" & x).Value = rs![name3]
Sheet1.Range("D" & x).Value = rs![name4]
.
.'lot more columns
.
Sheet1.Range("AC" & x).Value = rs![name28]
If x = 10 Then 'after each 10 lines to create another sheet
x = 6
j = j + 1
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name ="Sheet" & j
End If
Loop
cn.Close
Set cn = Nothing
Set rs = Nothing
Set cmdSQLData = Nothing
I need that when there are more "lines" in the record set than lets say 10, to have another sheet created, Sheet2, where to have the next 10 lines inserted and if the record set still has values to have another sheet created, Sheet3 and so on, until the record set has been fully parsed.
The problem is that for getting the data from record set to excel, i use Sheet1, hardcoded. I tryed to use instead of Sheet1, Sheet[j] or Sheet(j) and to increment "j" each time I create a new sheet, but I get an error, therefore I cannot use Sheet[j].Range("A" & x).Value=rs![name1] or Sheet(j).Range("A" & x).Value=rs![name1].
Any hints?
While I personally believe that collecting all data into one sheet before dividing them into set of x rows is much better, there's another way of going about it using your code. Instead of using Sheet1, use Sheets(j) where j is the sheet index. Also, you can do Sheets("Sheet" & j) as well.
Using the second approach, replace the respective block of your code with the following:
Set rs = cmdSQLData.Execute()
j = 1
x = 6 'the line I want the data to start
rs.MoveFirst
Do Until rs.EOF
With Sheets("Sheet" & j)
.Range("A" & x).Value = rs![name1]
.Range("B" & x).Value = rs![name2]
.Range("C" & x).Value = rs![name3]
.Range("D" & x).Value = rs![name4]
.
.'lot more columns
.
.Range("AC" & x).Value = rs![name28]
End With
x = x + 1
If x = 16 Then 'after each 10 lines to create another sheet
x = 6
j = j + 1
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "Sheet" & j
End If
Loop
You also forgot to increment your x so it will keep on overwriting row 6 again and again. Here, you should be targeting x=10 but x=16 since you start from row 6 based on the initial value of x. The ten rows including row 6 ends in row 15. Once x is equal to 16, it should trigger your IF block.
I have corrected that for you in the above code. Let us know if this helps.
Try this for adding new sheet:
Do Until rs.EOF
If x = 10 Then
Set ws = Thisworkbook.Sheets.Add(After:=Thisworkbook.Sheets(Thisworksheet.Sheets.Count)
ws.Name = "Sheet" & j
x = 6
j = j + 1 ' although you don't really need this, sheet number increment automatically.
End If
ws.Range("A" & x).Value = rs![name1]
.
.
x = x + 1
Loop
i just assumed you only have problem on adding sheet.
Hope this helps.
Related
I'm writing a macro to balance NBA stats. I'm getting an error with this function and don't know why. Sheets 5 and 6 and identical to Sheet 7. Confused why I'd be getting the error on Sheet 7 if all are identical. Also the code is the exact same for Sheet5 and Sheet 6 so shouldn't that remain the same for 7? I'm newer to VBA coding so trying to get any help even if it's simple. It just asks to debug and takes me directly here. Happy to share more code if needed
'Function to Obtain Team's Season Average Raw Stats
Function Grab_Team_Raw(t As String, team As String)
If t = "All" Then
a = 2
g = Sheet5.Cells(Rows.Count, "A").End(xlUp).Row
'Find Team's Row First
For a = 2 To g
tm = Sheet5.Cells(a, 1).Value
If tm = team Then
rw = a
End If
Next a
a = 2
g = Sheet5.Cells(rw, Columns.Count).End(xlToLeft).Column
For a = 2 To g
v = Sheet5.Cells(rw, a).Value
output = output & "," & v
Next a
ElseIf t = "Home" Then
a = 2
g = Sheet6.Cells(Rows.Count, "A").End(xlUp).Row
For a = 2 To g
tm = Sheet6.Cells(a, 1).Value
If tm = team Then
rw = a
End If
Next a
a = 2
g = Sheet6.Cells(rw, Columns.Count).End(xlToLeft).Column
For a = 2 To g
v = Sheet6.Cells(rw, a).Value
output = output & "," & v
Next a
Else
a = 2
g = Sheet7.Cells(Rows.Count, "A").End(xlUp).Row
For a = 2 To g
tm = Sheet7.Cells(a, 1).Value
If tm = team Then
rw = a
End If
Next a
a = 2
g = Sheet7.Cells(rw, Columns.Count).End(xlToLeft).Column
For a = 2 To g
v = Sheet7.Cells(rw, a).Value
output = output & "," & v
Next a
End If
Grab_Team_Raw = output
End Function
Half the effort needed for coding goes into designing variables, find their proper data types, and "meaningful" names for them. Start with Option Explicit.
Option Explicit
Function Grab_Team_Raw(t As String, team As String) As Variant
' Obtain Team's Season Average Raw Stats
' return a 2-D array of one row's data
Dim Ws As Worksheet ' working object
Dim Rw As Long ' loop counter: row
Select Case t
Case "All"
Set Ws = Sheet5
Case "Home"
Set Ws = Sheet6
Case Else
Set Ws = Sheet7
End Select
'Find Team's row
For Rw = Ws.Cells(Ws.Rows.Count, "A").End(xlUp).Row To 2 Step -1
If Ws.Cells(Rw, 1).Value = team Then Exit For
Next Rw
If Rw > 1 Then
With Ws ' observe all leading periods
Grab_Team_Raw = .Range(.Cells(Rw, 1), _
.Cells(Rw, .Columns.Count).End(xlToLeft)).Value
End With
Else
MsgBox team & " not found."
Exit Function
End If
End Function
I guess that your problem hails from this line of code which my above procedure inherited from the one you posted: If Ws.Cells(Rw, 1).Value = team. Try If StrComp(Ws.Cells(Rw, 1).Value, team, vbTextCompare) = 0 instead which makes the comparison case insensitive. But what you really need is a drop-down from which you select the names so that typos can be definitely ruled out.
Note that the function will return a 1-based 2-D array of one row. Access its elements like MyArr(1, Clm). The row is always 1 because there is only one row. The column matches the sheet column. A = 1, B = 2, etc. You wanted the array to start with column B which would have made B = 1, C = 2, etc. You can change that back in this line of code, Grab_Team_Raw = .Range(.Cells(Rw, 1), _
I have 1000s rows of data in 1 column that I need to transpose into columns, based on each row that is bold. The number of rows between bold ones is inconsistent, same as strings values.
I've created a simple code that worked perfectly while testing the first 100 rows. But when trying to run it through the entire list or some other parts (even 50 rows) it just stucks while running so I have to quite excel via task manager (with no error msg).
Sub Transpose_by_bold()
Dim x, y As Integer
y = 1
For x = 1 To 2000
If Range("B" & x).Font.Bold = True And Range("B" & x + 1).Font.Bold = True Then y = 1
If Range("B" & x).Font.Bold = True And Range("B" & x + 1).Font.Bold = False Then
Range("B" & x + 1).Cut Range("B" & x).Offset(0, y)
Range("B" & x + 1).EntireRow.Delete
y = y + 1
x = x - 1
End If
Next x
End Sub
I'd highly appreciate if you could give me a piece of idea what's wrong here?
Your code is currently hanging because once it moves to the end of the list X never increases, so it goes into an infinite loop. I've not tested FaneDuru's code, so it may be the answer, but the other choice would be to add some kind of escape clause to your code that bounces you out in the event of some condition you don't expect to ever happen naturally in your code - like a counter if range("b" & x).value = "" that gets reset when not true and, upon getting to some maximum value (say, 10 back to back empty cells) sets X equal to your max value (2000, in this case).
Don't forget, in the presence of weird stuff like this, you can step through your code with F8 and watch your values of X and Y in the Locals Window - if you do that, the fact that X gets stuck becomes quickly apparent.
sample counter (not terribly efficient, but it works):
Sub Transpose_by_bold()
Dim x, y As Integer
Dim Counter as Integer
y = 1
For x = 1 To 2000
If IsEmpty(Range("B" & x + 1)) Then
Counter = Counter + 1
Else
Counter = 0
End If
If Counter > 9 Then
x = 2001
End If
If Range("B" & x).Font.Bold = True And Range("B" & x + 1).Font.Bold = True Then y = 1
If Range("B" & x).Font.Bold = True And Range("B" & x + 1).Font.Bold = False Then
Range("B" & x + 1).Cut Range("B" & x).Offset(0, y)
Range("B" & x + 1).EntireRow.Delete
y = y + 1
x = x - 1
End If
Next x
End Sub
An alternate choice, I just realized (editing to note this), would be to count the maximum possible number of rows via an intersect of your column of interest and the used range of the sheet and then keep a counter that just checks how many total rows you've evaluated (your X counter right now is how many rows you'l end up with, not how many you've looked at, due to your x=x-1 line) and run your primary For loop on that total rows counter rather than on X.
Good luck!
Try the next code, please. I hope I could deduce the logic of your code. Especially, how to use y (incrementing the column to copy the range for each occurrence)... If the logic is correct, the code should be fast, deleting all rows at once:
Sub Transpose_by_bold()
Dim sh As Worksheet, x As Long, y As Long, rngDel As Range
Set sh = ActiveSheet 'use here your sheet
y = 1
For x = 1 To 2000
If Range("B" & x).Font.Bold = True And Range("B" & x + 1).Font.Bold = True Then y = 1
If Range("B" & x).Font.Bold = True And Range("B" & x + 1).Font.Bold = False Then
Range("B" & x).Offset(0, y).Value = Range("B" & x + 1).Value
If rngDel Is Nothing Then
Set rngDel = Range("B" & x + 1)
Else
Set rngDel = Union(rngDel, Range("B" & x + 1))
End If
y = y + 1
End If
Next x
If Not rngDel Is Nothing Then rngDel.EntireRow.Delete xlUp
End Sub
I have columns in my csv like this:
Id Name Price
1 Level X discontinued 34
3 Level Y Dicontinued 64
7 Level Z 94
I want to check if in column Name are discontinued or Dicontinued
If yes delete row, if not, dont do nothing, so my final result will be:
Id Name Price
7 Level Z 94
A solution can be running the following Excel Macro ExampleMacro with the following setup. This code will filter the first worksheet [here TotalList] copying the content in a second worksheet [here Filtered]
NOTE: please use the same names I used or change the code of the following macro accordingly if you prefer to change the names. Otherwise it will not work
Sub ExampleMacro()
Dim i As Integer
Dim j As Integer
Set ShMaster = ThisWorkbook.Sheets("TotalList")
Set ShSlave = ThisWorkbook.Sheets("Filtered")
'cleanup for next macro executions
ShSlave.UsedRange.Clear
'copying the headers
ShSlave.Range("A1").Value = ShMaster.Range("A1").Value
ShSlave.Range("B1").Value = ShMaster.Range("B1").Value
ShSlave.Range("C1").Value = ShMaster.Range("C1").Value
'searching what to keep
j = 2
For i = 2 To ShMaster.UsedRange.Rows.Count
'MsgBox "value is " & InStr(1, (Range("B" & i).Value), "discontinued")
If InStr(1, (ShMaster.Range("B" & i).Value), "discontinued") = 0 Then
While ShSlave.Range("C" & j).Value <> ""
j = j + 1
Wend
ShSlave.Range("A" & j).Value = ShMaster.Range("A" & i).Value
ShSlave.Range("B" & j).Value = ShMaster.Range("B" & i).Value
ShSlave.Range("C" & j).Value = ShMaster.Range("C" & i).Value
End If
Next i
End Sub
Following is part of my program which does the follwoing function
It will look into column K and column L and create tabs according to the combinations. For example if column K has a cell value "Apple" and column L has one cell value "Orange" it will create a tab 1) Apple - Orange
The new tab will have all the rows with this combination
So once complete the running of macro , the whole data will get divided to different tabs according to the K - L combination
My problem is it is giving a run time error when entire column K or entire column L has only one value. For example if entire K column has 10 rows and all column k cells has value Apple it will give error. same goes for column L.
Dim m As Integer
Dim area As Range
Count = Range("K:K").SpecialCells(xlLastCell).Row
ActiveSheet.Range("K2:K" & Count).AdvancedFilter Action:=xlFilterCopy,
CopyToRange:=ActiveSheet.Range("Z2"), Unique:=True
Columns(26).RemoveDuplicates Columns:=Array(1)
Count1 = Range("L:L").SpecialCells(xlLastCell).Row
ActiveSheet.Range("L2:L" & Count1).AdvancedFilter Action:=xlFilterCopy,
CopyToRange:=ActiveSheet.Range("Y2"), Unique:=True
Columns(25).RemoveDuplicates Columns:=Array(1)
Dim arrayv As String
Dim Text1 As String
Dim arrayv1 As String
last = Range("Z2").End(xlDown).Row
arrayv = WorksheetFunction.Transpose(Sheets(1).Range("Z2:Z" & last).Value)
last1 = Range("Y2").End(xlDown).Row
arrayv1 = WorksheetFunction.Transpose(Sheets(1).Range("Y2:Y" & last1).Value)
Columns(26).EntireColumn.Delete
Columns(25).EntireColumn.Delete
Dim i As Long, j As Long
Dim flag As Variant
flag = 1
A = 1
s = 2
For c = 1 To UBound(arrayv1)
For t = 1 To UBound(arrayv)
Sheets.Add().Name = "Sheet" & s
ActiveSheet.Move After:=Sheets(ActiveWorkbook.Sheets.Count)
With Worksheets("Sheet1")
j = 2
.Rows(1).Copy Destination:=Worksheets("Sheet" & s).Range("A" & 1)
flag = 1
For i = 2 To Count
If .Cells(i, 11).Value = arrayv(t) Then
If .Cells(i, 12).Value = arrayv1(c) Then
Text = .Cells(i, 15).Value
flag = 0
.Rows(i).Copy Destination:=Worksheets("Sheet" & s).Range("A" & j)
j = j + 1
End If
End If
Next i
If flag = 1 Then
Sheets("Sheet" & s).Delete
Else
Text1 = Left(Text, 4)
Error line when column K has only one value
arrayv = WorksheetFunction.Transpose(Sheets(1).Range("Z2:Z" & last).Value)
Error line when column L has only one value
arrayv1 = WorksheetFunction.Transpose(Sheets(1).Range("Y2:Y" & last1).Value)
If there is only one value Y2 or Z2 downwards then using the Range,End property with an xlDirection of xlDown is going to reference row 1,048,576. The WorksheetFunction.Transpose method has a limit of 65,536. Anything exceeding this limit will result in,
Run-time error '13':Type mismatch.
Change the direction of the last-row-seek to look up from the bottom with xlUp.
last = Range("Z" & rows.count).End(xlUp).Row
arrayv = WorksheetFunction.Transpose(Sheets(1).Range("Z2:Z" & last).Value)
last1 = Range("Y" & rows.count).End(xlUp).Row
arrayv1 = WorksheetFunction.Transpose(Sheets(1).Range("Y2:Y" & last1).Value)
In my worksheet some cells values are based on other cells
Info worksheet
A1: 5
B1: =A1
Design worksheet
A1:
Is there a way to copy and read the value in B1? I'm trying to use the value in a for loop, with no luck.
Sheets("Info").Select
For i = 1 to 5
If Range("B" & i).Value <> 0 Then
Range("B" & i).Copy Destination:=Sheets("Design").Range("A" & x)
'Sheets("Design").Range("A" & x).Value = Sheets("Offerte").Range("B" & i).Value
x = x + 1
End If
Next i
Your example doesn't seem to match the code well. The line
If Range("B" & i).Value = 1 Then
means that nothing will be copied in your example. It's looking for a cell with 1 in it. Why do you need that If statement at all?
EDIT I am guessing you're just checking that there's something in the cell to copy? I would probably do it this way:
If Trim(Range("B" & i).Value) <> "" Then
Also - did you miss out setting x=1?
There is more than one way to do it. One of them is using 'offset', which is a function that really worth understand. It basically points to a amount of rows / columns from the original cell.
Sub test()
Dim oCell As Excel.Range
Dim i As Integer
Dim x As Integer
Set oCell = Sheets("Info").Range("B1")
x = 1
For i = 1 To 5
If oCell.Offset(i, 0).Value = 1 Then
oCell.Offset(i, 0).Copy Destination:=Sheets("Design").Range("A" & x)
x = x + 1
End If
Next i
End Sub
Besides, you can assert the value instead of using the copy property. Notice it won't work unless x is an integer > 0.
Sub test2()
Sheets(3).Select
x = 1
For i = 1 To 5
If Range("B" & i).Value = 1 Then
Sheets(4).Range("A" & x).Value = Range("B" & i).Value
'Sheets("Design").Range("A" & x).Value = Sheets("Offerte").Range("B" & i).Value
x = x + 1
End If
Next i
End Sub