I am new to VBA and sitting with a sum, which includes three if loops. The code looks like this
Dim strKonto As String
Dim str?r As String
Dim strUdbetaling As String
Dim counter As Integer
Dim yearkbottom As Integer
Dim yearktop As Integer
For i = 1 To 50 'wsRefor.Cells(Rows.Count, 2).End(xlUp).Row
For k = 1 To 20 '200
yearkbottom = (wsRefor.Cells(k + 3, 1) - 2007) + 1
yearktop = (yearkbottom - 2007) + 4000
For j = yearkbottom To yearktop
strKonto = Right(wsArk7.Cells(j + 4, 2), 4)
str?r = wsArk7.Cells(j + 4, 1)
strUdbetaling = Left(wsArk7.Cells(j + 4, 2), 1)
counter = Val(str?r) - 2007
If wsRefor.Cells(i + 1, 2) = strKonto Then
If wsRefor.Cells(1, k + 3) = str?r Then
If strUdbetaling = 2 Then
wsRefor.Cells(i + 1, k + 3) = wsRefor.Cells(i + 1, k + 3) + wsArk7.Cells(j + 4, k + 2 - counter * 12)
End If
End If
End If
Next j
Next k
Next i
For the j-loop I tried to make the boundaries dynamic to make the calculations a little slower. That is, I am sure all values which the j loop finds are not spread over the entire range of j, but rather within the range defined above using k.
However, when I make this alteration I get an 1004 "Application-defined or Object-defined error".
Anyone able to spot the mistake, or alternatively to suggest any methods of speeding up the sum?
Best,
ID
EDIT: I found out what the problem was. The j counter took on zero at some point in the new boundaries, and when that happens (or when it is negative) the mistake I got comes up.
Thanks for the help!
Try below one. I have tried to do some fine tuning.
Dim strKonto As String
Dim strr As String
Dim strUdbetaling As String
Dim counter As Integer
Dim yearkbottom As Integer
Dim yearktop As Integer
Dim arryearkbottom(20) 'Declaring a Static Array of Size 21,(Starts from 0 index)
Dim arryearktop(20) 'Declaring a Static Array of Size 21,(Starts from 0 index)
'Initial Values
screenUpdateState = Application.ScreenUpdating
statusBarState = Application.DisplayStatusBar
calcState = Application.Calculation
eventsState = Application.EnableEvents
'Turning off the values for performance
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
'Reading all the values from sheet to Arrays
For i = 1 To 20
arryearkbottom(i) = (wsRefor.Cells(i + 3, 1) - 2007) + 1
arryearktop(i) = (arryearkbottom(i) - 2007) + 4000
Next
For i = 1 To 50 'wsRefor.Cells(Rows.Count, 2).End(xlUp).Row
For k = 1 To 20 '200
'yearkbottom = (wsRefor.Cells(k + 3, 1) - 2007) + 1
'yearktop = (yearkbottom - 2007) + 4000
For j = arryearkbottom(k) To arryearktop(k)
strKonto = Right(wsArk7.Cells(j + 4, 2), 4)
strr = wsArk7.Cells(j + 4, 1)
strUdbetaling = Left(wsArk7.Cells(j + 4, 2), 1)
counter = Val(strr) - 2007
If wsRefor.Cells(i + 1, 2) = strKonto Then
If wsRefor.Cells(1, k + 3) = strr Then
If strUdbetaling = 2 Then
wsRefor.Cells(i + 1, k + 3) = wsRefor.Cells(i + 1, k + 3) + wsArk7.Cells(j + 4, k + 2 - counter * 12)
End If
End If
End If
Next j
Next k
Next i
'Setting to Initial values
Application.ScreenUpdating = screenUpdateState
Application.DisplayStatusBar = statusBarState
Application.Calculation = calcState
Application.EnableEvents = eventsState
Solution2:
Dim strKonto As String
Dim strr As String
Dim strUdbetaling As String
Dim counter As Integer
Dim yearkbottom As Integer
Dim yearktop As Integer
Dim rngwsRefor As Range
Dim rngwsArk7 As Range
'Initial Values
screenUpdateState = Application.ScreenUpdating
statusBarState = Application.DisplayStatusBar
calcState = Application.Calculation
eventsState = Application.EnableEvents
'Turning off the values for performance
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
'Reading Entire sheet values to range
Set rngwsRefor = wsRefor.Cells
Set rngwsArk7 = wsArk7.Cells
For i = 1 To 50 'wsRefor.Cells(Rows.Count, 2).End(xlUp).Row
For k = 1 To 20 '200
yearkbottom = (rngwsRefor(k + 3, 1).Value - 2007) + 1
yearktop = (yearkbottom - 2007) + 4000
For j = yearkbottom To yearktop
strKonto = Right(rngwsArk7(j + 4, 2).Value, 4)
strr = rngwsArk7(j + 4, 1).Value
strUdbetaling = Left(rngwsArk7(j + 4, 2).Value, 1)
counter = Val(strr) - 2007
If rngwsRefor(i + 1, 2).Value = strKonto Then
If rngwsRefor(1, k + 3).Value = strr Then
If strUdbetaling = 2 Then
rngwsRefor(i + 1, k + 3).Value = rngwsRefor(i + 1, k + 3).Value + rngwsArk7.Cells(j + 4, k + 2 - counter * 12).Value
End If
End If
End If
Next j
Next k
Next i
'Setting to Initial values
Application.ScreenUpdating = screenUpdateState
Application.DisplayStatusBar = statusBarState
Application.Calculation = calcState
Application.EnableEvents = eventsState
Related
Good day to all,
I keep getting the same runtime error while executing my code. I don't have formal training in VBA (mostly some VB in highschool).
The code is this
Sub Lavaggi2():
Dim i, j, k, lavaggio, x, daymax As Integer
Dim day As Date
Dim Ore(10) As Single
Dim column_len, row_len As Integer
Dim totale_ore As Integer
'Determining variable for row and columns
column_len = Sheets("Foglio7").Cells.CurrentRegion.Columns.Count
row_len = Sheets("Foglio7").Cells.CurrentRegion.Rows.Count
k = 1
For j = 1 To row_len
For i = 1 To column_len
If (Sheets("Foglio7").Cells(2, i).Value = "Codice") Then
If (Sheets("Foglio7").Cells(j, i).Value = "00/100" Or Sheets("Foglio7").Cells(j, i).Value = "00/200") Then
day = Sheets("Foglio7").Cells(j, 1).Value
For k = 1 To 10
If (Sheets("Foglio7").Cells(j - k, 1).Value = day) Then
Ore(k) = Sheets("Foglio7").Cells(j - k, i + 5).Value
daymax = daymax + 1
Else
End If
Next k
totale_ore = Worksheet.funcion.Sum(Ore)
lavaggio = Sheets("Foglio7").Cells(j, i + 7) / totale_ore
For x = 1 To daymax
Sheets("Foglio7").Cells(j - x, i + 7).Value = lavaggio * Ore(x)
Next x
Erase Ore
End If
End If
Next i
Next j
End Sub
The line where I get the error is
If (Sheets("Foglio7").Cells(j - k, 1).Value = day) Then
I'm quite sure it's something silly but I'm unable to wrap my head around it.
PS: I'm aware that the code is probably a little clunky but I'll streamline it at a future stage.
Thanks to all who will answer
On your first iteration of the loop, j - k would equal 0, and your cell would be .Cells(0, 1), which doesn't exist.
I managed to solve the issues I encountered. It works as intended. Thanks to all for the help
Sub Lavaggi2():
Dim i, j, k, x, daymax As Integer
Dim day As Date
Dim lavaggio, totale_ore, Ore(10) As Double
Dim column_len, row_len As Integer
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
column_len = Sheets("Foglio7").Cells.CurrentRegion.Columns.Count
row_len = Sheets("Foglio7").Cells.CurrentRegion.Rows.Count
daymax = 1
For j = 1 To row_len
For i = 1 To column_len
If (Sheets("Foglio7").Cells(2, i).Value = "Codice") Then
If (Sheets("Foglio7").Cells(j, i).Value = "00/100" Or Sheets("Foglio7").Cells(j, i).Value = "00/200") Then
day = Sheets("Foglio7").Cells(j, 1).Value
For k = 1 To 10
If (Sheets("Foglio7").Cells(j - k, 1).Value = day) Then
Ore(k) = Sheets("Foglio7").Cells(j - k, i + 5).Value
daymax = daymax + 1
Else
Exit For
End If
Next k
totale_ore = Application.WorksheetFunction.Sum(Ore)
lavaggio = Sheets("Foglio7").Cells(j, i + 7) / totale_ore
For x = 1 To daymax - 1
Sheets("Foglio7").Cells(j - x, i + 7).Value = lavaggio * Ore(x)
Next x
daymax = 1
Erase Ore
End If
End If
Next i
Next j
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
I also tweaked the declarations in order to achieve the desired precision in the final results.
I have written the following code for one of my worksheets.
Sub Hide_Projects()
Application.ScreenUpdating = False
i = 6
For i = 6 To 350
Cells(9, i).Select
If Selection.Value = "Project" Then
ActiveCell.EntireColumn.Hidden = True
Else
ActiveCell.EntireColumn.Hidden = False
End If
Next i
Application.ScreenUpdating = True
End Sub
It works fine, does exactly what I need it to every time without crashing or lagging. However, when I use a similar code on a different worksheet, only this time applied to rows rather than columns, it either crashes my Excel or takes about 2 minutes to run, even though the code is identical. This is the second code:
Sub Hide_Projects_5yr()
Application.ScreenUpdating = False
i = 6
For i = 6 To 350
Cells(i, 7).Select
If Selection.Value = "Project" Then
ActiveCell.EntireRow.Hidden = True
Else
ActiveCell.EntireRow.Hidden = False
End If
Next i
Application.ScreenUpdating = True
End Sub
Does anyone have any idea why this is the case?
Thank you!
Obviously columns are times faster to hide than rows. I have tried this:
Option Explicit
Public Sub TestingSpeed()
Dim lngCount As Long
Dim dtTime As Date
Columns.Hidden = False
rows.Hidden = False
dtTime = Now
For lngCount = 1 To 300
rows(lngCount).Hidden = True
Next lngCount
Debug.Print "Rows: -> "; DateDiff("s", dtTime, Now())
dtTime = Now
For lngCount = 1 To 300
Columns(lngCount).Hidden = True
Next lngCount
Debug.Print "Cols: -> "; DateDiff("s", dtTime, Now())
End Sub
The result is the following (in seconds):
Rows: -> 9
Cols: -> 2
And the difference grows somehow exponentially.
With 1.000 samples it is like this:
Rows: -> 11
Cols: -> 1
With 10.000 like this:
Rows: -> 19
Cols: -> 10
It is very likely that your active sheet is not the one you intend to work on. It is always best to avoid Select and ActiveCell, because you are dependent on the cursor location. Not sure you need the false case, unless you use the same sheet over and over again and it may be hidden.
Sub Hide_Projects_5yr()
Application.ScreenUpdating = False
Dim ws as Worksheet
Set ws = Sheets("YourSheetName")
For i = 6 To 350
If ws.Cells(i, 7).Value = "Project" Then
ws.Cells(i, 7).EntireRow.Hidden = True
Else
ws.Cells(i, 7).EntireRow.Hidden = False
End If
Next i
Application.ScreenUpdating = True
End Sub
Could you try giving your code full addresses to your cells? Besides, it is a good idea not using the select command. Here's my modifications to your code:
Sub Hide_Projects()
Application.ScreenUpdating = False
With ThisWorkbook.Sheets("Put the name of your sheet here")
For i = 6 To 350
If .Cells(9, i).Text = "Project" Then
.Columns(i).Hidden = True
Else
.Columns(i).Hidden = False
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
Your second code would look like this:
Sub Hide_Projects_5yr()
Application.ScreenUpdating = False
With ThisWorkbook.Sheets("Put the name of your second sheet here")
For i = 6 To 350
If .Cells(i, 7).Text = "Project" Then
.Rows(i).Hidden = True
Else
.Rows(i).Hidden = False
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
Let me know if the error message keeps appearing.
Your main slowdown is a result of reading data from the worksheet too many times. Load the cell values into an array first, then loop through that.
You can also gain a bit of speed by unhiding the rows all at once at the outset, then hiding if the "="Project" condition is true. Again, this reduces the number of calls to the worksheet; your current version sets the ".Hidden" property of each row one-by-one.
Application.ScreenUpdating = False
Dim i As Long
Dim j As Long
Dim tempArr As Variant
tempArr = Range(Cells(6, 7), Cells(350, 7)).Value
Rows("6:350").Hidden = False
j = 1
For i = LBound(tempArr, 1) To UBound(tempArr, 1)
If tempArr(i, 1) = "Project" Then
Rows(j + 5).Hidden = True
End If
j = j + 1
Next
Application.ScreenUpdating = True
If you're really concerned about speed, you could also reduce the number of trips to the worksheet by checking for consecutive rows containing "Project". This version runs ~2x as fast as the other one (tested on a sample of 200k rows). It makes the code a lot more complex, though.
Application.ScreenUpdating = False
Dim i As Long
Dim j As Long
Dim k As Long
Dim tempArr As Variant
Dim consBool As Boolean
tempArr = Range(Cells(6, 7), Cells(350, 7)).Value
Rows("6:350").Hidden = False
j = 1
For i = LBound(tempArr, 1) To UBound(tempArr, 1)
consBool = True
If tempArr(i, 1) = "Project" Then
k = i
Do Until consBool = False
If k = UBound(tempArr, 1) Then
consBool = False
ElseIf tempArr(k + 1, 1) = "Project" Then
k = k + 1
Else
consBool = False
End If
Loop
Rows(j + 5 & ":" & k + 5).Hidden = True
j = j + 1 + (k - i)
i = k
Else
j = j + 1
End If
Next
Application.ScreenUpdating = True
Here's what it'd look like if I were going to implement this in a larger project. Among other optimizations, I've added some features (it can check for partial matches, check multiple columns for your criteria, and do an "inverted" mode that hides all rows not containing your criteria) and made sure that you're required to specify your worksheet.
Option Explicit
Sub exampleMacro()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Call hideRows(ThisWorkbook.Sheets("Example WS"), 6, 350, "Project", 7, 7)
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Sub hideRows(ws As Worksheet, startRow As Long, endRow As Long, valCrit As String, Optional startCol As Long = 1, Optional endCol As Long = 1, Optional invert As Boolean = False, Optional checkAll As Boolean = False)
'Hides rows in a range (startRow to endRow) in a worksheet (ws)
'Hides when row contains a value (valCrit; partial strings are accepted) in a column or series of columns (startCol to endCol)
'In inverted mode (invert), hides rows that do *not* contain value
'If (checkAll) is True, all columns must contain value to be hidden/unhidden
'Usage examples:
'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10) -> hides rows that contain a cell in columns 1-10 with exact value "Foo"
'Call hideRows(exampleWS, 1, 1000, "*Foo*", 1, 10) -> hides rows that contain a cell in columns 1-10 that contains partial string "*Foo*"
'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10, True) -> hides rows that contain no cells in columns 1-10 with exact value "Foo"
'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10, False, True) -> hides rows in which all cells in columns 1-10 contain the exact value "Foo"
'Call hideRows(exampleWS, 1, 1000, "Foo", 1, 10, True, True) -> hides rows in which no cells in columns 1-10 contain the exact value "Foo"
Dim loopCounter As Long
Dim rowCounter As Long
Dim colCounter As Long
Dim endConsRow As Long
Dim tempArr As Variant
Dim toAdd As Long
Dim toHide As String
Dim consBool As Boolean
Dim tempBool As Boolean
Dim rowStr As String
Dim goAhead As Boolean
Dim i As Long
If startRow > endRow Then
toAdd = endRow - 1
Else
toAdd = startRow - 1
End If
ws.Rows(startRow & ":" & endRow).Hidden = False
tempArr = ws.Range(ws.Cells(startRow, startCol), ws.Cells(endRow, endCol)).Value
loopCounter = 1
For rowCounter = LBound(tempArr, 1) To UBound(tempArr, 1)
For colCounter = LBound(tempArr, 2) To UBound(tempArr, 2)
goAhead = False
If tempArr(rowCounter, colCounter) Like valCrit Then
If (Not checkAll) Or (colCounter = UBound(tempArr, 2)) Then
If invert Then
loopCounter = loopCounter + 1
Exit For
End If
goAhead = True
End If
ElseIf checkAll Or colCounter = UBound(tempArr, 2) Then
If Not invert Then
loopCounter = loopCounter + 1
Exit For
End If
goAhead = True
End If
If goAhead Then
endConsRow = rowCounter
consBool = True
Do Until consBool = False
tempBool = False
For i = LBound(tempArr, 2) To UBound(tempArr, 2)
If endConsRow = UBound(tempArr, 1) Then
Exit For
ElseIf tempArr(endConsRow + 1, i) Like valCrit Then
If (Not checkAll) Or (i = UBound(tempArr, 2)) Then
If Not invert Then
endConsRow = endConsRow + 1
tempBool = True
End If
Exit For
End If
ElseIf checkAll Or i = UBound(tempArr, 2) Then
If invert Then
endConsRow = endConsRow + 1
tempBool = True
End If
Exit For
End If
Next
If Not tempBool Then
consBool = False
End If
Loop
rowStr = loopCounter + toAdd & ":" & endConsRow + toAdd
If toHide = "" Then
toHide = rowStr
ElseIf Len(toHide & "," & rowStr) > 255 Then
ws.Range(toHide).EntireRow.Hidden = True
toHide = rowStr
Else
toHide = toHide & "," & rowStr
End If
loopCounter = loopCounter + 1 + (endConsRow - rowCounter)
rowCounter = endConsRow
Exit For
End If
Next
Next
If Not toHide = "" Then
ws.Range(toHide).EntireRow.Hidden = True
End If
End Sub
I would like to be able to copy around 30k rows (to be exact, just some elements of the rows) from sheet A to sheet B, starting the destination from row nr 36155. Sometimes, we copy the row more than once, depending on the number in the G column. This is the macro I've written:
Sub copy()
ActiveSheet.DisplayPageBreaks = False
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculate
Dim k As Long, k1 As Long, i As Integer
k = 36155
k1 = 30000
For i = 1 To k1
For j = 1 To Sheets("A").Range("G" & i + 2).Value
Sheets("B").Range("A" & k).Value = Sheets("A").Range("A" & i + 2).Value
Sheets("B").Range("B" & k).Value = Sheets("A").Range("B" & i + 2).Value
Sheets("B").Range("C" & k).Value = j
Sheets("B").Range("D" & k).Value = Sheets("A").Range("C" & i + 2).Value
Sheets("B").Range("E" & k).Value = Sheets("A").Range("D" & i + 2).Value
Sheets("B").Range("F" & k).Value = Sheets("A").Range("E" & i + 2).Value
Sheets("B").Range("G" & k).Value = Sheets("A").Range("F" & i + 2).Value
Sheets("B").Range("H" & k).Value = Sheets("A").Range("I" & i + 2).Value + (j - 1) * Sheets("A").Range("H" & i + 2).Value
Sheets("B").Range("I" & k).Value = Sheets("A").Range("J" & i + 2).Value
k = k + 1
Next j
Next i
Application.EnableEvents = True
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Unfortunately, this macro takes a lot of time to run (around 10 minutes). I have a feeling that, there may be a better way to do that.. Do you have any ideas, how can we enchance the macro?
Try this using variant arrays: could be even faster if you can use a B array containing more than 1 row. This version takes 17 seconds on my PC.
Sub Copy2()
ActiveSheet.DisplayPageBreaks = False
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculate
'
Dim k As Long, k1 As Long, i As Long, j As Long
Dim varAdata As Variant
Dim varBdata() As Variant
'
Dim dT As Double
'
dT = Now()
'
k = 36155
k1 = 30000
'
' get sheet A data into variant array
'
varAdata = Worksheets("A").Range("A1:J1").Resize(k1 + 2).Value2
'
For i = 1 To k1
'For j = 1 To Sheets("A").Range("G" & i + 2).Value
For j = 1 To varAdata(i + 2, 7)
'
' create empty row of data for sheet B and fill from variant array of A data
'
ReDim varBdata(1 to 1,1 to 9) As Variant
'Sheets("B").Range("A" & k).Value = Sheets("A").Range("A" & i + 2).Value
varBdata(1, 1) = varAdata(i + 2, 1)
varBdata(1, 2) = varAdata(i + 2, 2)
varBdata(1, 3) = j
varBdata(1, 4) = varAdata(i + 2, 3)
varBdata(1, 5) = varAdata(i + 2, 4)
varBdata(1, 6) = varAdata(i + 2, 5)
varBdata(1, 7) = varAdata(i + 2, 6)
varBdata(1, 8) = varAdata(i + 2, 9) + (j - 1) * varAdata(i + 2, 8)
varBdata(1, 9) = varAdata(i + 2, 10)
'
' write to sheet B
'
Sheets("B").Range("A1:I1").Offset(k - 1).Value2 = varBdata
k = k + 1
Next j
Next i
'
Application.EnableEvents = True
Application.CutCopyMode = False
Application.ScreenUpdating = True
MsgBox (Now() - dT)
End Sub
I would suggest you read your data into a recordset as shown here, then loop the recordset.
Try the following (untested).
Sub copy()
With Application
.ScreenUpdating = False
.EnableEvents = False
.Calculate
.Calculation = xlCalculationManual
End With
Dim k As Long, i As Integer
k = 36155
' read data into a recordset
Dim rst As Object
Set rst = GetRecordset(ThisWorkbook.Sheets("A").UsedRange) 'feel free to hard-code your range here
With rst
While Not .EOF
For j = 1 To !FieldG
' !FieldG accesses the Datafield with the header "FieldG". Change this to the header you actually got in Column G, like "!MyColumnG" or ![columnG with blanks]
Sheets("B").Cells(k, 1).Value = !FieldA
' ... your code
k = k + 1
Next j
.movenext
Wend
End With
With Application
.EnableEvents = True
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
End Sub
Also add the following Function into your VBA Module.
Function GetRecordset(rng As Range) As Object
'Recordset ohne Connection:
'https://usefulgyaan.wordpress.com/2013/07/11/vba-trick-of-the-week-range-to-recordset-without-making-connection/
Dim xlXML As Object
Dim rst As Object
Set rst = CreateObject("ADODB.Recordset")
Set xlXML = CreateObject("MSXML2.DOMDocument")
xlXML.LoadXML rng.Value(xlRangeValueMSPersistXML)
rst.Open xlXML
Set GetRecordset = rst
End Function
Note:
- using a recordset gives you additional options like filtering data
- with a recordset, your not dependent on the column-order of your input-data, meaning you don't have to adjust your macro if you decide to add another column to sheet A (as long as you keep the headers the same)
Hope this helps.
I'm making an app in Excel-VBA, but when I have more than 50,000 records, code runs very slow, the formatting takes about 33 seconds.
Application.Interactive = False
Application.EnableEvents = False
Application.ScreenUpdating = False
'--------------- Tao Bien ------------------------------------------
Dim Dulieu() As Variant
Dim lastrow As Integer
Dim lastrowSC As Integer
Dim i, j As Integer
Dim NoDk, CoDk As Double
Dim PSNo As Double
Dim PSCo As Double
Dim NoCk As Double
Dim CoCk As Double
Dim TempArray() As Variant
Dim TheRange As Range
Dim Size As Integer
Dim TempArrayDao() As Variant
Dim lastrowTK As Integer
Dim TaiKhoan() As Variant
Dim FromDate As Date
Dim ToDate As Date
'--------------------Do Toc Do--------------------------------------
Dim Starttime As Double
Dim Code1 As Double
Dim Code2 As Double
Dim Code3 As Double
Dim Code4 As Double
Dim Code5 As Double
Dim Code6 As Double
Dim Code7 As Double
Starttime = Timer
'--------------- Xong Tao Bien --------------------------------------
NoDk = 0
CoDk = 0
PSNo = 0
PSCo = 0
NoCk = 0
CoCk = 0
lastrow = Sheet8.Cells(Rows.Count, "I").End(xlUp).Row
'Them so du dau ky----------------------------------------------------
lastrowTK = Sheet7.Cells(Rows.Count, "A").End(xlUp).Row
TaiKhoan = Sheet7.Range("A2:H" & lastrowTK)
For i = LBound(TaiKhoan) To UBound(TaiKhoan)
If Sheet26.Cells(4, 4).Text = TaiKhoan(i, 1) Then
NoDk = TaiKhoan(i, 3)
CoDk = TaiKhoan(i, 4)
Sheet26.Cells(5, 3).Value = "Tên tài kho" & ChrW(7843) & "n : " & TaiKhoan(i, 2)
Exit For
End If
Next
Code1 = Round(Timer - Starttime, 2)
'----------------------------------------------------------------------
Dim NoCongDon As Double
Dim CoCongDon As Double
Sheet26.Select
' Dua Du lieu vao Array Dulieu
Dulieu = Sheet8.Range("G2:N" & lastrow).Value
FromDate = Sheet26.Cells(6, 3).Value
ToDate = Sheet26.Cells(7, 3).Value
Size = 1
ReDim TempArray(1 To 6, 1 To Size)
Dim tk As String
tk = Sheet26.Cells(4, 4).Text
For i = 1 To UBound(Dulieu)
If ((StrComp(Left(tk, Len(Trim(tk))), Left(Dulieu(i, 6), Len(Trim(tk))), vbTextCompare) = 0) Or _
(StrComp(Left(tk, Len(Trim(tk))), Left(Dulieu(i, 7), Len(Trim(tk))), vbTextCompare) = 0)) Then
If (StrComp(Left(tk, Len(Trim(tk))), Left(Dulieu(i, 6), Len(Trim(tk))), vbTextCompare) = 0) Then
If Dulieu(i, 3) < FromDate Then
NoCongDon = NoCongDon + Dulieu(i, 8)
ElseIf Dulieu(i, 3) = FromDate Or Dulieu(i, 3) <= ToDate Then
TempArray(1, Size) = Dulieu(i, 1)
TempArray(2, Size) = Dulieu(i, 3)
TempArray(3, Size) = Dulieu(i, 5)
TempArray(4, Size) = Dulieu(i, 7)
TempArray(5, Size) = Dulieu(i, 8)
Size = Size + 1
ReDim Preserve TempArray(1 To 6, 1 To Size)
End If
Else
If Dulieu(i, 3) < FromDate Then
CoCongDon = CoCongDon + Dulieu(i, 8)
ElseIf Dulieu(i, 3) = FromDate Or Dulieu(i, 3) <= ToDate Then
TempArray(1, Size) = Dulieu(i, 1)
TempArray(2, Size) = Dulieu(i, 3)
TempArray(3, Size) = Dulieu(i, 5)
TempArray(4, Size) = Dulieu(i, 6)
TempArray(6, Size) = Dulieu(i, 8)
Size = Size + 1
ReDim Preserve TempArray(1 To 6, 1 To Size)
End If
End If
End If
Next i
Code2 = Round(Timer - Starttime, 2)
'Dao lai Array Tam
ReDim TempArrayDao(1 To Size, 1 To 6)
For i = 1 To Size
For j = 1 To 6
TempArrayDao(i, j) = TempArray(j, i)
Next
Next
k = UBound(TempArrayDao) + 14
'Add value to my sheet
Set TheRange = Sheet26.Range("A15:F" & k)
TheRange.Value = TempArrayDao
Format my sheet, is take me 33s to format my sheet, i don't know why ..
With Sheet26
With .Range("A14:F" & k + 1)
.ClearFormats
.Borders.LineStyle = xlContinuous
End With
Code4 = Round(Timer - Starttime, 2) ' code4 is 0.4 s
With .Range("C14:C" & k)
.WrapText = True
.Rows.AutoFit
.VerticalAlignment = xlCenter
End With
Code5 = Round(Timer - Starttime, 2) 'code5 is 13,14s
.Range("A14:B" & k).HorizontalAlignment = xlCenter
.Range("A14:B" & k).VerticalAlignment = xlCenter
With .Range("D14:D" & k)
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.NumberFormat = "#"
End With
With .Range("E14:F" & k + 1)
.NumberFormat = "_(* #,##0_);_(* (#,##0);_(* ""-""??_);_(#_)"
.VerticalAlignment = xlCenter
End With
.Range("C" & k & ":C" & k + 1).HorizontalAlignment = xlCenter
.Range("B14:B" & k).NumberFormat = "dd/mm/yyyy"
Code6 = Round(Timer - Starttime, 2) ' code6 is 33,97 s
End With
With Sheet26.Range("A" & k & ":F" & k + 1)
.Interior.ThemeColor = xlThemeColorDark2
.Font.Bold = True
End With
ReDim Dulieu(0, 0) As Variant
ReDim TempArray(0, 0) As Variant
Set TheRange = Nothing
ReDim TempArrayDao(0, 0) As Variant
ReDim TaiKhoan(0, 0) As Variant
Application.Interactive = True
Application.EnableEvents = True
Application.ScreenUpdating = True
I'm trying to record a macro in which if the text in a column header is the same as the text in a row the intersection cell of the row and the column gets highlighted.
For example:
A11: "description"
Y1: "description"
->Y11 should be highlighted
Your answer doesn't seem to intuitively answer the question at hand: How to highlight an intersecting row and column on found match?
A naive approach would be to iterate through the columns and rows to find matches:
Private Sub ColorIntersection()
Application.EnableEvents = False
Application.ScreenUpdating = False
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim cols As Range, rws As Range
Dim lastRow As Integer: lastRow = ws.UsedRange.Rows.Count
Dim lastColumn As Integer: lastColumn = ws.UsedRange.Columns.Count
For Each cols In ws.Range(ws.Cells(1, 1), ws.Cells(1, lastColumn))
If (Not (cols.Value = vbNullString)) Then
For Each rws In ws.Range("A1:A" & lastRow)
If (rws.Value = cols.Value) Then ws.Cells(rws.Row, cols.Column).Interior.Color = 5296210
Next
End If
Next
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
So this is what it is. Works perfectly with what I need (it also highlights a number of cells ahead of the one on the intersection)
Sub BorderForNonEmpty2()
Dim wb As Workbook
Dim wsCurrent As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set wb = ActiveWorkbook
Set wsCurrent = wb.ActiveSheet
Dim atLastCompareDate As Boolean
Dim atLastMPDate As Boolean
Dim mPDateCounter As Integer
Dim compareDateCounter As Integer
mPDateCounter = 3
'loop over each row where the value in column c is not empty, starting at row 3
Do While Not atLastMPDate
Dim mPDate As String
mPDate = wsCurrent.Range("C" + CStr(mPDateCounter)).Value
atLastCompareDate = False
If (mPDate = Null Or mPDate = "") Then
atLastMPDate = True
Else
'loop over each column where the value in row 1 is not empty, starting at column e
compareDateCounter = 5
Do While (Not atLastCompareDate)
Dim compareDate As String
Dim currentCellColumn As String
If (compareDateCounter <= 26) Then
currentCellColumn = Chr((compareDateCounter) + 96)
Else
If (compareDateCounter > 26) And (compareDateCounter Mod 26 = 0) Then
currentCellColumn = Chr(Int(compareDateCounter / 26) - 1 + 96) + Chr(122)
Else
currentCellColumn = Chr(Int(compareDateCounter / 26) + 96) + Chr((compareDateCounter Mod 26) + 96)
End If
End If
compareDate = wsCurrent.Range(currentCellColumn + CStr(1)).Value
If (compareDate = Null Or compareDate = "") Then
atLastCompareDate = True
Else
If (compareDate = mPDate) Then
Dim cellLocation As String
If (compareDateCounter <= 26) Then
cellLocation = Chr((compareDateCounter) + 96)
Else
If (compareDateCounter > 26) And (compareDateCounter Mod 26 = 0) Then
cellLocation = Chr(Int(compareDateCounter / 26) - 1 + 96) + Chr(122)
Else
cellLocation = Chr(Int(compareDateCounter / 26) + 96) + Chr((compareDateCounter Mod 26) + 96)
End If
End If
wsCurrent.Range(cellLocation + CStr(mPDateCounter)).Interior.ColorIndex = 11
'Loop backwards to mark the 6 dates before
Dim i As Integer
i = compareDateCounter - 1
Do While (i > compareDateCounter - 7)
If (i <= 26) Then
cellLocation = Chr((i) + 96)
Else
If (i > 26) And (i Mod 26 = 0) Then
cellLocation = Chr(Int(i / 26) - 1 + 96) + Chr(122)
Else
cellLocation = Chr(Int(i / 26) + 96) + Chr((i Mod 26) + 96)
End If
End If
wsCurrent.Range(cellLocation + CStr(mPDateCounter)).Interior.ColorIndex = 43
wsCurrent.Range(cellLocation + CStr(mPDateCounter)).Borders.LineStyle = xlContinuous
wsCurrent.Range(cellLocation + CStr(mPDateCounter)).Borders.ColorIndex = 11
i = i - 1
Loop
atLastCompareDate = True
End If
End If
compareDateCounter = compareDateCounter + 1
Loop
End If
mPDateCounter = mPDateCounter + 1
Loop
End Sub