I'm trying to utilize a dynamically created userform and based on what boxes are check, gray out certain cells.
As background, this is for an injection molding facility. QA sets up the cavity numbers that are running. This dynamic userform creates checkboxes based on the cavity numbers that are input on the worksheet.
Option Explicit
Private Sub UserForm_Initialize()
Dim col As Long
Dim row As Long
Dim lcol As Long
Dim i As Long
Dim j As Long
Dim chkBox As MsForms.CheckBox
Dim l As MsForms.Frame
Dim t As MsForms.Label
Set l = Me.Controls.Add("Forms.Frame.1", "cavz", True)
l.Caption = "BLOCKED CAVITIES"
l.Height = 195
Set t = l.Controls.Add("Forms.Label.1", "mark")
t.Caption = "Mark all cavities that are currently blocked:"
t.Width = 175
t.Top = 10
col = 2 'Set your column index here
row = 8
lcol = 17
j = 1
For i = col To lcol
Set chkBox = l.Controls.Add("Forms.CheckBox.1", "CheckBox_" & i)
If Worksheets("QA").Cells(row, i).Value <> "" Then
chkBox.Caption = Worksheets("QA").Cells(row, i).Value
ElseIf Worksheets("QA").Cells(row, i).Value = "" Then
GoTo 10
End If
If i <= 9 Then
'MsgBox "i = " & i
chkBox.Left = 5
chkBox.Top = 5 + ((i - 1) * 20)
ElseIf i > 9 Then
j = j + 1
'MsgBox "j = " & j
chkBox.Left = 100
chkBox.Top = 5 + ((j - 1) * 20)
End If
10
Next i
End Sub
Private Sub CommandButton2_Click()
Unload Me
End Sub
Private Sub CommandButton1_Click()
Dim x As Control
Dim cavz As MsForms.Frame
For Each x In cavz.Controls
If x.Value = True Then
If x.Value = Range("B8") Then
Range("B8:B14").Select
Selection.Interior.ColorIndex = 16
End If
End If
Next x
End Sub
I started out doing one thing, and somehow this is what my code turned into. It's not the neatest code, but I would still consider myself a novice at this. Plus, this is the first time I couldn't find the answer on my own and thus my first time asking for help. So, any help would be greatly appreciated!
Thanks!
UPDATE
This is great! Thank you Don. However, I do have a follow up question. Perhaps I've been banging my head against this for too long, but I cannot think of a more efficient way to do this. Here is what I'm now doing:
For i = 2 To 17
Set ctl = Controls.Item("CheckBox_" & i)
If ctl = True Then
If i = 2 Then
Range(Cells(j, c), Cells(m, c)).Select
Selection.Interior.ColorIndex = 16
Range(Cells(k, c), Cells(m, c)).Select
With Selection
.Merge
Cells(k, c) = "BLOCKED"
.Orientation = 90
.VerticalAlignment = xlCenter
.HorizontalAlignment = xlCenter
End With
End If
Next i
etc
I'm in the process of writing if i = 1 through 17, but I feel like there's a more efficient way and I just can't crack it.
Loop through them by name the same way you created them.
Dim ctl As Control
For i = 2 To 17
Set ctl = Controls.Item("CheckBox_" & i)
Next 'i
Also, I would create module level constants for the initial values of col, lcol, etc. and reuse those in both routines.
Related
I've written the below code to modify a speadsheet that has tens of thousands of lines. Whenever I run the code, it burns through the lines fast enough, will complete about 10k lines in 3-4 minutes or so. But every time I run it, it gets to about line 25K or so, and crashes, telling me I don't have enough memory, and will suggest upgrading to 64-bit. I have a macro that created the sheet without incident, and it's much more complex, so seems odd this code crashes it. Anything in this code that you'd think would cause my issue? Or is 64-bit likely the right fix?
Sub TPOUploadCADUplicate()
'This takes the TPO Mass upload sheet and duplicates it below for Canada. Unlike above, it doesn't do anything to the US part on top
Dim Answer As String
Dim BigMarkup As Double
Dim CAPrice As Double
Dim Cost As Double
Dim i As Long
Dim rn As Long
Dim rn2 As Long
Dim SKUCount As Double
Dim STMarkup As Double
Dim USPrice As Double
Dim lr As Long
Dim DescLen As Integer
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
'Make sure you didn't accidentally leave the description length column in
If Cells(1, 3) <> "VENDOR # (9 SPACES)" Then
DescLen = MsgBox("Yo, bro. I think you left the description length column in. You want to delete that shit? I can't proceed otherwise.", vbYesNo)
If DescLen = 6 Then
Columns(3).Delete
ElseIf DescLen = 7 Then
Exit Sub
End If
End If
Columns(6).NumberFormat = "#.00"
'Loop through each one, doing the math from the TPO price calculator Connie has
If Cells(2, 1) = "" Then Exit Sub
rn = Cells(1, 1).End(xlDown).Row
rn2 = rn + 1
rn = 2
SKUCount = rn2 - rn
For i = 1 To SKUCount
Application.StatusBar = "Progress: " & i & " of " & SKUCount & " - " & Format(i / SKUCount, "0%")
Rows(rn2).Value = Rows(rn).Value
USPrice = Cells(rn, 4)
If USPrice * CAMarkup < 20 Then
CAPrice = Round((USPrice) * CAMarkup, 1) + 0.09
Else
CAPrice = WorksheetFunction.RoundDown((USPrice) * CAMarkup, 0) + 0.99
End If
Cells(rn2, 4) = CAPrice
Cells(rn2, 6).Value = Cells(rn2, 6).Value * CAMarkup
Cells(rn2, 22) = "CAM"
rn = rn + 1
rn2 = rn2 + 1
Next i
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.StatusBar = False
End With
End Sub
Might be better (faster) to read all the data to an array, then work on the array, before putting it on the sheet after the existing data.
Sub TPOUploadCADUplicate()
Dim ans
Dim CAPrice As Double
Dim SKUCount As Double
Dim STMarkup As Double, CAMarkup As Double
Dim USPrice As Double
Dim DescLen As Integer, ws As Worksheet, arr, lr As Long, lc As Long, r As Long
Set ws = ActiveSheet 'best to be explicit about which sheet you're working with
'Make sure you didn't accidentally leave the description length column in
If ws.Cells(1, 3) <> "VENDOR # (9 SPACES)" Then
ans = MsgBox("Yo, bro. I think you left the description length column in. " & _
"You want to delete that shit? I can't proceed otherwise.", vbYesNo)
If ans <> vbYes Then Exit Sub
ws.Columns(3).Delete
End If
ws.Columns(6).NumberFormat = "#.00"
lr = ws.Cells(Rows.Count, "A").End(xlUp).Row 'last row
If lr = 1 Then Exit Sub 'no data?
lc = ws.Cells(1, Columns.Count).End(xlToLeft).Column 'last column
CAMarkup = 1.1 '<< for example
arr = ws.Range("A2", ws.Cells(lr, lc)).value 'copy the existing data as an array
For r = 1 To UBound(arr, 1) 'loop over the array and make adjustments
USPrice = arr(r, 4)
If USPrice * CAMarkup < 20 Then
CAPrice = Round((USPrice) * CAMarkup, 1) + 0.09
Else
CAPrice = WorksheetFunction.RoundDown((USPrice) * CAMarkup, 0) + 0.99
End If
arr(r, 4) = CAPrice
arr(r, 6) = arr(r, 6) * CAMarkup
arr(r, 22) = "CAM"
Next r
'put the data on the sheet
ws.Cells(lr + 1, "A").Resize(UBound(arr, 1), UBound(arr, 2)).value = arr
End Sub
I have a userform that I've created that first asks how many rows I would like to insert. The next part of the userform asks what values I would like in columns 1 and 32 of each newly created row (I've set it up so that a maximum of 6 new rows can be created at one time). My data has 45 columns, and the only data that I want to change in the newly created rows is the data in the two columns i said earlier (1 and 32). I want the data from all the other columns from the original row to be copied down into each new row. My problem is that I can't seem to figure out how to write a code that will do this the way I want it. To provide an example, if I respond to the userform that I want to add 3 rows below the currently active cell, it will then ask me what values i want to enter for columns 1 and 32 for each of these new rows. So I would enter something like this:
First New Row
Column 1: 8/17/2019
Column 32: 400
Second New Row
Column 1: 8/10/2019
Column 32: 500
Third New Row
Column 1: 8/3/2019
Column 32: 600
I've tried many different codes but I've only really figured out how to write it so that it inserts one row below the active cell and its completely blank, I don't know how to program it so that it enters he values I selected for columns 1 and 32 and copies all other data down from the original row. I've figured out the code for the clear and cancel button on my userform already, I am now only concerned with writing this code for the "OK" button.
Private Sub CancelButton_Click()
Unload Me
End Sub
Private Sub ClearButton_Click()
Call UserForm_Initialize
End Sub
Private Sub OKButton_Click()
Dim lRow As Long
Dim lRsp As Long
On Error Resume Next
lRow = Selection.Row()
lRsp = MsgBox("Insert New row above " & lRow & "?", _
vbQuestion + vbYesNo)
If lRsp <> vbYes Then Exit Sub
Rows(lRow).Select
Selection.Copy
Rows(lRow + 1).Select
Selection.Insert Shift:=xlDown
Application.CutCopyMode = False
Rows(lRow).PasteSpecial Paste:=xlPasteFormulas, Operation:=xlNone
End Sub
Private Sub UserForm_Initialize()
AddRowsTextBox.Value = ""
Date1TextBox.Value = ""
Date2TextBox.Value = ""
Date3TextBox.Value = ""
Date4TextBox.Value = ""
Date5TextBox.Value = ""
Date6TextBox.Value = ""
Qty1TextBox.Value = ""
Qty2TextBox.Value = ""
Qty3TextBox.Value = ""
Qty4TextBox.Value = ""
Qty5TextBox.Value = ""
Qty6TextBox.Value = ""
End Sub
what i understand from your requirement, I would have add one more spin button on the form to make it user friendly. It may look like this.
User form Code may please be modified according to control names in your form
Option Explicit
Public Bal As Double, XQnty As Double, LargeOrder As Double, Sm As Double
Private Sub CommandButton1_Click()
Dim lRow As Long
Dim lRsp As Long
lRow = ActiveCell.Row()
lRsp = MsgBox("Insert New row Below " & lRow & "?", vbQuestion + vbYesNo)
If lRsp <> vbYes Then Exit Sub
Dim Ws As Worksheet
Dim R As Long, i As Integer, RowtoAdd As Integer
Set Ws = ThisWorkbook.ActiveSheet
RowtoAdd = Me.SpinButton1.Value
R = ActiveCell.Row
With Ws
.Cells(R, 32).Value = LargeOrder
For i = 1 To RowtoAdd
.Cells(R + 1, 1).EntireRow.Insert Shift:=xlDown
.Cells(R, 1).EntireRow.Copy Destination:=.Cells(R + 1, 1)
.Cells(R + 1, 1).Value = Me.Controls("TextBox" & i).Value
.Cells(R + 1, 32).Value = Me.Controls("TextBox" & 7 + i).Value
R = R + 1
Next i
End With
Unload Me
End Sub
Private Sub CommandButton2_Click()
Unload Me
End Sub
Private Sub SpinButton1_Change()
Dim x As Integer, i As Integer, Y As Double
Me.TextBox7.Value = Me.SpinButton1.Value
x = Me.SpinButton1.Value
Sm = 0
For i = 1 To 6
Me.Controls("TextBox" & i).BackColor = IIf(i <= x, RGB(255, 100, 100), RGB(255, 2550, 255))
Me.Controls("TextBox" & i + 7).Value = IIf(i <= x, Int(Bal / x), 0)
Sm = Sm + IIf(i <= x, Int(Bal / x), 0)
Next
If Sm <> Bal Then
Me.TextBox8.Value = Int(Bal / x) + Bal - Sm
End If
ManualBal
End Sub
Private Sub TB_LO_Change()
LargeOrder = Val(Me.TB_LO.Value)
Bal = XQnty - LargeOrder
ManualBal
End Sub
Private Sub UserForm_Initialize()
Dim i As Integer, dx As Variant
Me.SpinButton1.Value = 1
Me.TextBox7.Value = 1
Me.TextBox1.BackColor = RGB(255, 100, 100)
dx = ThisWorkbook.ActiveSheet.Cells(ActiveCell.Row, 1).Value
XQnty = ThisWorkbook.ActiveSheet.Cells(ActiveCell.Row, 32).Value
LargeOrder = 575
Bal = XQnty - LargeOrder
Sm = 0
If IsDate(dx) = False Then dx = Now()
For i = 1 To 6
Me.Controls("TextBox" & i).Value = Format(dx - i * 7, "mm-dd-yyyy")
Sm = Sm + Int(Bal / 6)
Me.Controls("TextBox" & i + 7).Value = Int(Bal / 6)
Next
If Sm <> Bal Then
Me.TextBox8.Value = Int(Bal / 6) + Bal - Sm
End If
Me.TB_LO = LargeOrder
Me.TB_Bal = 0
End Sub
Private Sub ManualBal()
Dim x As Integer, i As Integer
x = Me.SpinButton1.Value
Bal = XQnty - LargeOrder
Sm = 0
For i = 1 To 6 ' Or may use 6 insted of X
Sm = Sm + Val(Me.Controls("TextBox" & i + 7).Value)
Next
Me.TB_Bal.Value = Bal - Sm
End Sub
Private Sub TextBox8_Exit(ByVal Cancel As MSForms.ReturnBoolean)
ManualBal
End Sub
Private Sub TextBox9_Exit(ByVal Cancel As MSForms.ReturnBoolean)
ManualBal
End Sub
Private Sub TextBox10_Exit(ByVal Cancel As MSForms.ReturnBoolean)
ManualBal
End Sub
Private Sub TextBox11_Exit(ByVal Cancel As MSForms.ReturnBoolean)
ManualBal
End Sub
Private Sub TextBox12_Exit(ByVal Cancel As MSForms.ReturnBoolean)
ManualBal
End Sub
Private Sub TextBox13_Exit(ByVal Cancel As MSForms.ReturnBoolean)
ManualBal
End Sub
Here Text Box 1 to 6 for dates, 7 for Spin Button values and Text Box 8 to 13 for quantity. May please either modify code according to control names Or modify Control names according to code.
Edit: Two new Text Box added named TB_BAL to show when entering values in manually in Quantity text boxes (balance calculated only at exit event of text boxes) and TB_LO to change LargeOrder during run.
I search any text within Worksheet2 and display the results in ListBox1.
Private Sub SearchButton_Click()
'ListBox1.Clear
ListBox1.RowSource = ""
ListBox1.ColumnHeads = False
'listbox column headers
Me.ListBox1.AddItem
For A = 1 To 8
Me.ListBox1.List(0, A - 1) = Sheet2.Cells(1, A)
Next A
Me.ListBox1.Selected(0) = True
'Populating listbox from search
Dim i As Long
For i = 2 To Sheet2.Range("A100000").End(xlUp).Offset(1, 0).Row
For j = 1 To 8
H = Application.WorksheetFunction.CountIf(Sheet2.Range("A" & i, "H" & i), Sheet2.Cells(i, j))
If H = 1 And LCase(Sheet2.Cells(i, j)) = LCase(Me.TextBox2) Or H = 1 And _
Sheet2.Cells(i, j) = Val(Me.TextBox2) Then
Me.ListBox1.AddItem
For X = 1 To 8
Me.ListBox1.List(ListBox1.ListCount - 1, X - 1) = Sheet2.Cells(i, X)
Next X
End If
Next j
Next i
End Sub
I want to search multiple worksheets instead but don't know how to achieve this without changing the code completely.
You're going to have to change the reference to Sheet2 if you want to look at multiple sheets. There's no way around that. But, it will make your code more flexible. Start by doing this:
Private Sub SearchButton_Click()
'ListBox1.Clear
ListBox1.RowSource = ""
ListBox1.ColumnHeads = False
'listbox column headers
Me.ListBox1.AddItem
For A = 1 To 8
Me.ListBox1.List(0, A - 1) = Sheet2.Cells(1, A)
Next A
Me.ListBox1.Selected(0) = True
Dim ws As Worksheet 'This is the new line of code where you define your worksheet
Set ws = ActiveWorkbook.Sheet2 'Replace all references below to Sheet2 with this
'Populating listbox from search
Dim i As Long
For i = 2 To ws.Range("A100000").End(xlUp).Offset(1, 0).Row
For j = 1 To 8
H = Application.WorksheetFunction.CountIf(ws.Range("A" & i, "H" & i), Sheet2.Cells(i, j))
If H = 1 And LCase(Sheet2.Cells(i, j)) = LCase(Me.TextBox2) Or H = 1 And _
ws.Cells(i, j) = Val(Me.TextBox2) Then
Me.ListBox1.AddItem
For X = 1 To 8
Me.ListBox1.List(ListBox1.ListCount - 1, X - 1) = Sheet2.Cells(i, X)
Next X
End If
Next j
Next i
End Sub
Now that you're generalized your Sub, you can modify the value of ws to repeat the code as much as you need to. If it is every sheet in your workbook, you can use a For Each loop, like
For Each ws In ActiveWorkbook
'All your code for the ws here
Next ws
Or, you can define the worksheets in an array beforehand.
Dim SheetList(0 to 2) As String
Dim k As Integer
SheetList(0) = "Sheet 2 Name"
SheetList(1) = "Sheet 4 Name"
SheetList(2) = "Sheet 3 Name"
SheetList(3) = "Sheet 6 Name"
For k = LBound(SheetList) To UBound(SheetList)
ws = ActiveWorkbook.Sheets(SheetList(k))
'The rest of your code from above
Next k
You didn't specify in your question what kind of sheets how many, or how they are organized. But, these options should be enough to get you where you are trying to go.
Below is a program in Excel VBA that creates a progress indicator. I've tried to make the progress indicator as simple as possible, yet it still looks elegant by using Unicode characters: full block and thin space.
Private Sub Play_Click()
Dim iCounter As Long, iRow As Long, nRow As Long, _
Block As String, Progress As Long, iChar As Long
Columns(1).ClearContents
With Cells(2, 4)
.ClearContents
.Font.Color = vbBlue
nRow = 100
For iRow = 1 To nRow
For iCounter = 1 To 100
Cells(iRow, 1) = iCounter
Next
Progress = Int(iRow / 10)
If Progress = iRow / 10 Then
Block = Block & ChrW(9608) & ChrW(8201)
'------------------
'Option statements
'------------------
End If
.Value = Block & " " & iRow & " %"
Next
End With
End Sub
I'd like to have the progress indicator looks like this
where the full blocks are always green-colored and the percentage number is always blue-colored while the program is running. But using these three option statements,
Option 1
.Characters(, 2 * Progress - 1).Font.Color = vbGreen
Option 2
For iChar = 1 To Len(.Value)
If Mid$(Text, iChar, 1) = ChrW(9608) Then
.Characters(iChar, 1).Font.Color = vbGreen
End If
Next
Option 3
GreenBlue 2 * Progress - 1
---------------------
Sub GreenBlue(GreenPart As Integer)
Select Case GreenPart
Case 1 To 19
Cells(2, 4).Characters(, GreenPart).Font.Color = vbGreen
End Select
End Sub
I kept getting the following output
What is the correct way to get the output like the first picture?
Whenever you replace the value of the cell, all of the new content will pick up its formatting from the first character being replaced, so the whole content will be green: need to first set the color back to blue if you want the numeric part to be blue
Private Sub Play_Click()
Dim iCounter As Long, iRow As Long, nRow As Long, _
Block As String, Progress As Long, iChar As Long, x As Long
Columns(1).ClearContents
With Cells(2, 4)
.ClearContents
.Font.Color = vbBlue
nRow = 100
For iRow = 1 To nRow
For iCounter = 1 To 100
Cells(iRow, 1) = iCounter
Next
Progress = Int(iRow / 10)
If Progress = iRow / 10 Then
Block = Block & ChrW(9608) & ChrW(8201)
End If
Application.ScreenUpdating = False 'reduce flashing during update
.Value = Block & " " & iRow & " %"
.Font.Color = vbBlue
If Len(Block) > 0 Then
.Characters(1, InStr(.Value, " ")).Font.Color = vbGreen
End If
Application.ScreenUpdating = True
'add some delay...
For x = 1 To 1000
DoEvents
Next x
Next
End With
End Sub
I've one workbook with 170K rows, I will delete all rows when the result between cells is 0,
For those operation, normally I use the code below, but with 170K (the rows will be deleted are 90K) the code run very slowly.
Someone know another way more performance.
Thank
Last = Cells(Rows.Count, "K").End(xlUp).Row
For i = Last To 2 Step -1
If (Cells(i, "K").Value + Cells(i, "L").Value) < 1 Then
Cells(i, "A").EntireRow.Delete
End If
Next i
As long as your fine putting the data on a new tab, the code below will do everything you need in 1.5 seconds.
Sub ExtractRows()
Dim vDataTable As Variant
Dim vNewDataTable As Variant
Dim vHeaders As Variant
Dim lastRow As Long
Dim i As Long, j As Long
Dim Counter1 As Long, Counter2 As Long
With Worksheets(1)
lastRow = .Cells(Rows.Count, "K").End(xlUp).row
vHeaders = .Range("A1:L1").Value2
vDataTable = .Range("A2:L" & lastRow).Value2
End With
For i = 1 To UBound(vDataTable)
If vDataTable(i, 11) + vDataTable(i, 12) > 0 Then
Counter1 = Counter1 + 1
End If
Next
ReDim vNewDataTable(1 To Counter1, 1 To 12)
For i = 1 To UBound(vDataTable)
If vDataTable(i, 11) + vDataTable(i, 12) > 0 Then
Counter2 = Counter2 + 1
For j = 1 To 12
vNewDataTable(Counter2, j) = vDataTable(i, j)
Next j
End If
Next
Worksheets.Add After:=Worksheets(1)
With Worksheets(2)
.Range("A1:L1") = vHeaders
.Range("A2:L" & Counter1 + 1) = vNewDataTable
End With
End Sub
Here, my approach for your problem according to rwilson's idea.
I already tested it. It very very reduce executing time. Try it.
Sub deleteRow()
Dim newSheet As Worksheet
Dim lastRow, newRow As Long
Dim sheetname As String
Dim startTime As Double
sheetname = "sheetname"
With Sheets(sheetname)
Set newSheet = ThisWorkbook.Worksheets.Add(After:=Sheets(.Name))
'Firstly copy header
newSheet.Rows(1).EntireRow.Value = .Rows(1).EntireRow.Value
lastRow = .Cells(.Rows.Count, "K").End(xlUp).row
newRow = 2
For row = 2 To lastRow Step 1
If (.Cells(row, "K").Value + .Cells(row, "L").Value) >= 1 Then
newSheet.Rows(newRow).EntireRow.Value = .Rows(row).EntireRow.Value
newRow = newRow + 1
End If
Next row
End With
Application.DisplayAlerts = False
Sheets(sheetname).Delete
Application.DisplayAlerts = True
newSheet.Name = sheetname
End Sub
Here is a non-VBA option you can try:
In column M compute the sum of columns K and L
Highlight column M and the click Find and select > Find
Type in 0 in the Find what box and also select values in the Look in box
Select Find all and in the box that shows the found items select all entires (click in the box and press CTRL + A)
On the ribbon select Delete and then Delete sheet rows
Now manually delete column M
I haven't tried this with 170k+ rows but maybe worth assessing performance versus the VBA loop.
thank at all for your ideas but the really fast code is: use an array tu populate whit the correct date and replare all table of the end sort the table:
Sub Macro13(control As IRibbonControl)
Dim avvio As Date
Dim arresto As Date
Dim tempo As Date
Application.ScreenUpdating = False
Application.Calculation = xlManual
avvio = Now()
Dim sh As Worksheet
Dim arng As Variant
Dim arrdb As Variant
Dim UR As Long, x As Long, y As Long
Dim MyCol As Integer
Set sh = Sheets("Rol_db")
MyCol = 1
sh.Select
UR = sh.Cells(Rows.Count, MyCol).End(xlUp).Row
ReDim arrdb(2 To UR, 1 To 12) As Variant
For x = 2 To UR
If Cells(x, 11) + Cells(x, 12) > 0 Then
For y = 1 To 12
arrdb(x, y) = Cells(x, y)
Next y
Else
For y = 1 To 12
arrdb(x, y) = ""
Next y
End If
Next x
sh.Range("A2:L" & UR) = arrdb
arresto = Now()
tempo = arresto - avvio
Debug.Print "Delete empty rows " & tempo
Range("A2:L" & UR).Sort key1:=Range("A2:L" & UR), _
order1:=xlAscending, Header:=xlNo
Range("A4").Select
ActiveWindow.FreezePanes = True
conclusioni:
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
time for my sheet 170K 00:00:07.
as soon as I have a minute I feel a loop of the columns