I am trying to write a macro in Excel which will allow me to automatically do groupings based on the number located in the first column. Here is the code.
Sub Makro1()
Dim maxRow As Integer
Dim row As Integer
Dim groupRow As Integer
Dim depth As Integer
Dim currentDepth As Integer
maxRow = Range("A65536").End(xlUp).row
For row = 1 To maxRow
depth = Cells(row, 1).Value
groupRow = row + 1
currentDepth = Cells(groupRow, 1).Value
If depth >= currentDepth Then
GoTo EndForLoop
End If
Do While currentDepth > depth And groupRow <= maxRow
groupRow = groupRow + 1
currentDepth = Cells(groupRow, 1).Value
Loop
Rows(row + 1 & ":" & groupRow - 1).Select
Selection.Rows.Group
EndForLoop:
Next row
End Sub
The first column in the Excel file looks like this:
1
2
2
3
3
4
4
4
4
5
5
5
6
6
6
6
5
6
6
6
7
8
8
9
10
9
10
10
8
7
7
8
6
5
4
3
2
1
2
When the macro reaches the depth 8 speaking of the groupings, I get error number 1004. It looks like the Excel does not allow me to create a depth greater than 8. Is there a workaround for this? I am using MS Excel 2003.
You are out of luck.
There is an 8 level limit for grouping which
also exists in xl07
on my testing exists in xl2010 (gives "Group method of range class failed")
I wrote this code to hide the sublevel rows, like grouping does.
it needs the first row empty, where the general level buttons will be placed.
it will create a button (placed in the first column) for each node with sublevels.
Clicking on the buttons will hide/unhide the corresponding sublevels.
the check_col is a colum that must be filled up to the last rows (i.e. no blank rows, or the "while" loop will stop
the lvl_col is the column that contains the level index
the start_row is the first row that contains useful data
hope this helps
Sub group_tree()
check_col = "A"
lvl_col = "D"
start_row = 3
Dim btn As Button
Application.ScreenUpdating = False
ActiveSheet.Buttons.Delete
Dim t As Range
'------------Place the buttons on top--------------
i = start_row
e_lvl = 0
b_spac = 0
b_width = 20
b_toggle = 0
While Range(check_col & i) <> ""
lvl = Range(lvl_col & i)
If lvl > e_lvl Then e_lvl = lvl
i = i + 1
Wend
Set t = ActiveSheet.Range("A" & 1)
For c = Range(lvl_col & start_row) To e_lvl
Set btn = ActiveSheet.Buttons.Add(t.Left + b_spac, t.Top, b_width, 10)
With btn
.OnAction = "btnS_t"
.Caption = c
.Name = start_row & "_" & c & "_" & lvl_col & "_" & b_toggle
End With
b_spac = b_spac + 20
Next
'--------------Place the buttons at level---------
i = start_row
While Range(check_col & i) <> ""
lvl = Range(lvl_col & i)
If Range(lvl_col & i + 1) > lvl Then
Set t = ActiveSheet.Range("A" & i)
' Set btn = ActiveSheet.Buttons.Add(t.Left, t.Top, t.Width, t.Height)
Set btn = ActiveSheet.Buttons.Add(t.Left, t.Top, b_width, 10)
With btn
.OnAction = "btnS"
.Caption = lvl
.Name = i & "_" & lvl & "_" & lvl_col
End With
End If
i = i + 1
Wend
Application.ScreenUpdating = True
End Sub
Sub btnS()
Dim but_r As Integer
Set b = ActiveSheet.Buttons(Application.Caller)
id_string = b.Name
Dim id() As String
id = Split(id_string, "_")
start_row = CInt(id(0))
start_lvl = CInt(id(1))
lvl_col = id(2)
' MsgBox (lvl_col)
Call hide_rows(start_lvl, start_row, lvl_col)
End Sub
Sub hide_rows(start_lvl, start_row, lvl_col)
a = start_row + 1
While Range(lvl_col & a) > start_lvl
a = a + 1
Wend
If Range(lvl_col & start_row + 1, lvl_col & a - 1).EntireRow.Hidden = False Then
Range(lvl_col & start_row + 1, lvl_col & a - 1).EntireRow.Hidden = True
Else
Range(lvl_col & start_row + 1, lvl_col & a - 1).EntireRow.Hidden = False
End If
End Sub
Sub btnS_t()
Dim but_r As Integer
Set b = ActiveSheet.Buttons(Application.Caller)
id_string = b.Name
Dim id() As String
id = Split(id_string, "_")
start_row = CInt(id(0))
start_lvl = CInt(id(1))
lvl_col = id(2)
b_toggle = CInt(id(3))
If b_toggle = 0 Then
b_toggle = 1
Else
b_toggle = 0
End If
b.Name = start_row & "_" & start_lvl & "_" & lvl_col & "_" & b_toggle
Call hide_rows_tot(start_lvl, start_row, lvl_col, b_toggle)
End Sub
Sub hide_rows_tot(start_lvl, start_row, lvl_col, b_toggle)
a = start_row
While Range(lvl_col & a) <> ""
b = a
While Range(lvl_col & b) > start_lvl
b = b + 1
Wend
If b > a Then
If b_toggle = 1 Then
Range(lvl_col & a, lvl_col & b - 1).EntireRow.Hidden = True
Else
Range(lvl_col & a, lvl_col & b - 1).EntireRow.Hidden = False
End If
a = b - 1
End If
a = a + 1
Wend
End Sub
Related
I am a newbie vba coder here.
I have created an .xlsm with userform. Everything works fine in my computer, but when I send the file over via email, the recipient will encounter the following issues when opening the file:
I added an event handler on Workbook_Open to automatically open the userform. When the recipient open the file, it will receive this error and Debug button returns to this line:
When Submit button of the Userform is clicked, the data is supposed to be transferred to 'ThisWorkbook' but instead it creates a new file (i guess the previous version) and paste the data there.
Can anyone help me to figure out what went wrong with my file? Thank you.
Below is my code:
Inside Workbook Event Handler:
Sub Workbook_Open()
RunForm
End Sub
Module1:
Option Explicit
Option Base 1
Sub PopulateComboBox()
Dim PaymentTerms() As String, PaymentFreq() As String, PaymentTermsAlt() As String
Dim i As Integer, j As Integer, m As Integer, n As Integer, o As Integer
j = WorksheetFunction.CountA(Sheets("Populate").Columns("A:A"))
n = WorksheetFunction.CountA(Sheets("Populate").Columns("B:B"))
ReDim PaymentTerms(j - 1) As String
ReDim PaymentFreq(n - 1) As String
ReDim PaymentTermsAlt(j - 1) As String
For i = 1 To j - 1
PaymentTerms(i) = ThisWorkbook.Sheets("Populate").Range("A2:A" & (j - 1)).Cells(i, 1)
UserForm1.ComboTerms.AddItem PaymentTerms(i)
Next i
For m = 1 To n - 1
PaymentFreq(m) = ThisWorkbook.Sheets("Populate").Range("B2:B" & (n - 1)).Cells(m, 1)
UserForm1.ComboFreq.AddItem PaymentFreq(m)
Next m
For o = 1 To j - 1
PaymentTermsAlt(o) = ThisWorkbook.Sheets("Populate").Range("A2:A" & (j - 1)).Cells(o, 1)
UserForm1.ComboTermsAlt.AddItem PaymentTermsAlt(o)
Next o
UserForm1.ComboTerms.Text = PaymentTerms(1)
UserForm1.ComboFreq.Text = PaymentFreq(1)
UserForm1.ComboTermsAlt.Text = PaymentTermsAlt(1)
End Sub
Sub RunForm()
ThisWorkbook.Sheets("Printout").Activate
UserForm1.Show
End Sub
Inside Userform:
Option Explicit
Sub CommandButton1_Click()
Application.ScreenUpdating = False
If Not IsNumeric(BasePay) Or Not IsNumeric(Interest) Then
MsgBox ("Please Enter Numeric Value for Base Pay or Interest Rate")
Exit Sub
End If
If BasePay < 0 Or Interest < 0 Then
MsgBox ("Base Pay or Interest cannot be negative value")
Exit Sub
End If
ThisWorkbook.Sheets("Printout").Range("A1") = "Prepared For " & ClientName
ThisWorkbook.Sheets("Printout").Range("O1").Value = BasePay.Text
ThisWorkbook.Sheets("Printout").Range("S2").Value = Interest.Text / 100
ThisWorkbook.Sheets("Printout").Range("L3").Value = ComboTerms.Text
ThisWorkbook.Sheets("Printout").Range("O3").Value = ComboFreq.Text
ThisWorkbook.Sheets("Printout").Range("Q2").Value = ComboTermsAlt.Text
If NewCar Then
ThisWorkbook.Sheets("Printout").Range("U2").Value = "New"
Else
ThisWorkbook.Sheets("Printout").Range("U2").Value = "Used"
End If
'----- Transfer Add-On Items to Printout Sheet ---------
Dim i As Integer
Dim j As Integer
Dim k As Integer
k = 6
For i = 1 To 9
ThisWorkbook.Sheets("Printout").Cells(k, 1).MergeArea.ClearContents
k = k + 2
Next
k = 6
For i = 10 To 18
ThisWorkbook.Sheets("Printout").Cells(k, 5).MergeArea.ClearContents
k = k + 2
Next
k = 6
For i = 19 To 27
ThisWorkbook.Sheets("Printout").Cells(k, 9).MergeArea.ClearContents
k = k + 2
Next
k = 6
For i = 28 To 36
ThisWorkbook.Sheets("Printout").Cells(k, 13).MergeArea.ClearContents
k = k + 2
Next
'---- Category 1 ------
i = 6
For j = 1 To 9
If UserForm1.Controls("Checkbox" & j).Value = True Then
ThisWorkbook.Sheets("Printout").Range("A" & i).Value = Me.Controls("Checkbox" & j).Caption
i = i + 2
Else
ThisWorkbook.Sheets("Printout").Range("A" & i).Value = ""
End If
Next j
'---- Category 2 ------
i = 6
For j = 10 To 18
If UserForm1.Controls("Checkbox" & j).Value = True Then
ThisWorkbook.Sheets("Printout").Range("E" & i).Value = Me.Controls("Checkbox" & j).Caption
i = i + 2
Else
ThisWorkbook.Sheets("Printout").Range("E" & i).Value = ""
End If
Next j
'---- Category 3 ------
i = 6
For j = 19 To 27
If UserForm1.Controls("Checkbox" & j).Value = True Then
ThisWorkbook.Sheets("Printout").Range("I" & i).Value = Me.Controls("Checkbox" & j).Caption
i = i + 2
Else
ThisWorkbook.Sheets("Printout").Range("I" & i).Value = ""
End If
Next j
'---- Category 4 ------
i = 6
For j = 28 To 36
If UserForm1.Controls("Checkbox" & j).Value = True Then
ThisWorkbook.Sheets("Printout").Range("M" & i).Value = Me.Controls("Checkbox" & j).Caption
i = i + 2
Else
ThisWorkbook.Sheets("Printout").Range("M" & i).Value = ""
End If
Next j
UserForm1.Hide
End Sub
Sub CommandButton2_Click()
Unload UserForm1
UserForm1.Show
End Sub
Sub CommandButton3_Click()
Unload UserForm1
End Sub
Sub NewCar_Click()
Dim LastRow As Integer
Dim i As Integer
Dim j As Integer
LastRow = WorksheetFunction.CountA(Sheets("Populate").Columns("D:D"))
'---- Count No of Checkbox
Dim Ctrl As MSForms.Control
Dim n As Integer
Dim cbcount As Long
For n = 0 To Me.Controls.Count - 1
If Left(UserForm1.Controls(n).Name, 8) = "CheckBox" Then
cbcount = cbcount + 1
End If
Next n
i = 2 '--- Preset counter i
For j = 1 To cbcount
UserForm1.Controls("Checkbox" & j).Caption = ThisWorkbook.Sheets("Populate").Cells(i, 4).Value
i = i + 1
If i > LastRow And i < (cbcount / 4) Then
UserForm1.Controls("Checkbox" & j).Caption = ""
End If
If i > LastRow And i > (cbcount / 4 + 1) Then
i = 2
End If
Next j
End Sub
Sub UsedCar_Click()
Dim LastRow As Integer
Dim i As Integer
Dim j As Integer
LastRow = WorksheetFunction.CountA(Sheets("Populate").Columns("D:D"))
'---- Count No of Checkbox
Dim Ctrl As MSForms.Control
Dim n As Integer
Dim cbcount As Long
For n = 0 To Me.Controls.Count - 1
If Left(Me.Controls(n).Name, 8) = "CheckBox" Then
cbcount = cbcount + 1
End If
Next n
i = 2 '--- Preset counter i
For j = 1 To cbcount
UserForm1.Controls("Checkbox" & j).Caption = ThisWorkbook.Sheets("Populate").Cells(i, 8).Value
i = i + 1
If i > LastRow And i < (cbcount / 4) Then
UserForm1.Controls("Checkbox" & j).Caption = ""
End If
If i > LastRow And i > (cbcount / 4 + 1) Then
i = 2
End If
Next j
End Sub
Sub UserForm_Initialize()
Call PopulateComboBox
'----- Rename Frame Boxes Caption
Dim k As Integer, nc As Integer
nc = 1
For k = 2 To 5
Me.Controls("Frame" & k).Caption = ThisWorkbook.Sheets("Printout").Cells(5, nc)
nc = nc + 4
Next k
'--------------------------------------------------
Dim LastRow As Integer
Dim i As Integer
Dim j As Integer
LastRow = WorksheetFunction.CountA(ThisWorkbook.Sheets("Populate").Columns("D:D"))
'---- Count No of Checkbox
Dim Ctrl As MSForms.Control
Dim n As Integer
Dim cbcount As Long
For n = 0 To Me.Controls.Count - 1
If Left(Me.Controls(n).Name, 8) = "CheckBox" Then
cbcount = cbcount + 1
End If
Next n
i = 2 '--- Preset counter i
For j = 1 To cbcount
UserForm1.Controls("Checkbox" & j).Caption = ThisWorkbook.Sheets("Populate").Cells(i, 4).Value
i = i + 1
If i > LastRow And i < (cbcount / 4) Then
UserForm1.Controls("Checkbox" & j).Caption = ""
End If
If i > LastRow And i > (cbcount / 4 + 1) Then
i = 2
End If
Next j
End Sub
I figure there must be a way to drastically shorten this sub procedure. The reason why I even want to is because it's freezing up the application on the elseif userform1.optTerm line because that worksheet it pulls the data from is 6x longer in rows than the optInSeat list.
Sub LoadEmployee_Cmb_HC()
Dim isWS As Worksheet: Set isWS = ThisWorkbook.Worksheets("In Seat")
Dim tWs As Worksheet: Set tWs = ThisWorkbook.Worksheets("Terms")
Dim a, b As Long, c As Variant, i As Long
If UserForm1.optInSeat = True Then
If UserForm1.optEmployeeName = True Then
For i = 2 To isWS.Cells(Rows.Count, 4).End(xlUp).row
x = Application.CountIf(isWS.Range("D" & 4, "D" & i), _
isWS.Cells(i, 4).Value)
If x = 1 Then
UserForm1.cmbEmployee.AddItem isWS.Cells(i, 4) & " - " & isWS.Cells(i, 1)
End If
Next i
For a = 0 To UserForm1.cmbEmployee.ListCount - 1
For b = 0 To UserForm1.cmbEmployee.ListCount - 1
If UserForm1.cmbEmployee.List(b) > UserForm1.cmbEmployee.List(a) Then
c = UserForm1.cmbEmployee.List(a)
UserForm1.cmbEmployee.List(a) = UserForm1.cmbEmployee.List(b)
UserForm1.cmbEmployee.List(b) = c
End If
Next
Next
ElseIf UserForm1.optEmployeeID = True Then
For i = 2 To isWS.Cells(Rows.Count, 1).End(xlUp).row
x = Application.CountIf(isWS.Range("A" & 1, "A" & i), _
isWS.Cells(i, 1).Value)
If x = 1 Then
UserForm1.cmbEmployee.AddItem isWS.Cells(i, 1) & " - " & isWS.Cells(i, 4)
End If
Next i
For a = 0 To UserForm1.cmbEmployee.ListCount - 1
For b = 0 To UserForm1.cmbEmployee.ListCount - 1
If UserForm1.cmbEmployee.List(b) > UserForm1.cmbEmployee.List(a) Then
c = UserForm1.cmbEmployee.List(a)
UserForm1.cmbEmployee.List(a) = UserForm1.cmbEmployee.List(b)
UserForm1.cmbEmployee.List(b) = c
End If
Next
Next
End If
ElseIf UserForm1.optTerm = True Then
If UserForm1.optEmployeeName = True Then
For i = 2 To tWs.Cells(Rows.Count, 4).End(xlUp).row
x = Application.CountIf(tWs.Range("D" & 4, "D" & i), _
tWs.Cells(i, 4).Value)
If x = 1 Then
UserForm1.cmbEmployee.AddItem tWs.Cells(i, 4) & " - " & tWs.Cells(i, 1)
End If
Next i
For a = 0 To UserForm1.cmbEmployee.ListCount - 1
For b = 0 To UserForm1.cmbEmployee.ListCount - 1
If UserForm1.cmbEmployee.List(b) > UserForm1.cmbEmployee.List(a) Then
c = UserForm1.cmbEmployee.List(a)
UserForm1.cmbEmployee.List(a) = UserForm1.cmbEmployee.List(b)
UserForm1.cmbEmployee.List(b) = c
End If
Next
Next
ElseIf UserForm1.optEmployeeID = True Then
For i = 2 To tWs.Cells(Rows.Count, 1).End(xlUp).row
x = Application.CountIf(tWs.Range("A" & 1, "A" & i), _
tWs.Cells(i, 1).Value)
If x = 1 Then
UserForm1.cmbEmployee.AddItem tWs.Cells(i, 1) & " - " & tWs.Cells(i, 4)
End If
Next i
For a = 0 To UserForm1.cmbEmployee.ListCount - 1
For b = 0 To UserForm1.cmbEmployee.ListCount - 1
If UserForm1.cmbEmployee.List(b) > UserForm1.cmbEmployee.List(a) Then
c = UserForm1.cmbEmployee.List(a)
UserForm1.cmbEmployee.List(a) = UserForm1.cmbEmployee.List(b)
UserForm1.cmbEmployee.List(b) = c
End If
Next
Next
End If
End If
End Sub
Instead of trying to shape the data using code, I would suggest creating an SQL statement based on runtime logic, opening a recordset with that data, and pushing the result back into the combobox.
Add a reference (Tools -> References...) to Microsoft ActiveX Data Objects; the latest version, usually 6.1.
(Credit goes to CDP1802's answer, which is the basis for much of the logic here.)
Dim source As String
If optInSeat = True Then
source = "'In Seat$'"
ElseIf optTerm = True Then
source = "Terms$"
End If
If Len(source) = 0 Then Exit Sub ' Do nothing
' sort by columns
Dim orderBy As String, expr As String
If optEmployeeName Then
expr = "Trim(F1) & ' - ' & Trim(F4)"
orderBy = "F1, F4"
ElseIf optEmployeeID Then
expr = "Trim(F4) & ' - ' & Trim(F1)"
orderBy = "F4, F1"
Else
expr = "Trim(F1) & ' - ' & Trim(F4)"
End If
Dim connectionString As String
connectionString = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=""" & ThisWorkbook.FullName & """;" & _
"Extended Properties=""Excel 12.0;HDR=No"""
Dim sql As String
sql = _
"SELECT " & expr & " " & _
"FROM [" & source & "]"
If Len(orderBy) > 0 Then sql = sql & " ORDER BY " & orderBy
Dim rs As New ADODB.Recordset
rs.Open sql, connectionString
' The 2D array comes back in the wrong direction to be set directly.
' We use WorksheetFunctions.Transpose to switch the direction.
cmbEmployees.List = WorksheetFunction.Transpose(rs.GetRows)
Select unique items using a Dictionary Object and sort them in an array. This sorts in ascending order.
Sub LoadEmployee_Cmb_HC()
Dim wb As Workbook, ws As Worksheet
Dim dict, k As String, i As Long
Dim order(2) As Integer
Set wb = ThisWorkbook
Set dict = CreateObject("Scripting.Dictionary")
' data source
If UserForm1.optInSeat = True Then
Set ws = wb.Sheets("In Seat")
ElseIf UserForm1.optTerm = True Then
Set ws = wb.Sheets("Terms")
End If
' sort by columns
If UserForm1.optEmployeeName = True Then
order(1) = 4: order(2) = 1
ElseIf UserForm1.optEmployeeID = True Then
order(1) = 1: order(2) = 4
End If
If order(1) = 0 Or ws Is Nothing Then
' do nothing
Else
' get unique values start in row 4
For i = 4 To ws.Cells(Rows.Count, order(1)).End(xlUp).Row
k = Trim(ws.Cells(i, order(1)).Value)
If Len(k) > 0 And Not dict.exists(k) Then
dict.Add k, k & " - " & Trim(ws.Cells(i, order(2)))
End If
Next
' sort and populate combo
Call SortCombo(dict, UserForm1.ComboBox1)
End If
End Sub
Sub SortCombo(ByRef dict, cmb As ComboBox)
Dim ar, a As Long, b As Long, i As Long, tmp As String
ar = dict.keys
i = UBound(ar)
For a = 0 To i
For b = a To i
If ar(b) < ar(a) Then
tmp = ar(a)
ar(a) = ar(b)
ar(b) = tmp
End If
Next
ar(a) = dict.Item(ar(a)) ' replace with value after it sort
Next
cmb.List = ar
End Sub
Alternative sort using temporary sheet
Sub SortCombo2(ByRef dict, cmb As ComboBox)
Dim wsTmp As Worksheet, rng As Range, k, ar() As String, i As Long
Set wsTmp = ThisWorkbook.Sheets(3)
wsTmp.Cells.Clear
ReDim ar(dict.Count - 1, 0)
i = 0
For Each k In dict.keys
ar(i, 0) = dict(k)
i = i + 1
Next
Set rng = wsTmp.Range("A1:A" & dict.Count)
rng = ar
With wsTmp.Sort
.SetRange rng
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.Apply
End With
cmb.List = rng.Value2
wsTmp.Cells.Clear
End Sub
Test data generator
Sub data()
Dim ws As Worksheet, i, s, n
Set ws = Sheets("Terms")
ws.Cells.Clear
For i = 4 To 35000
s = ""
For n = 1 To 25
s = s & Chr(65 + Int(Rnd() * 26))
Next
ws.Cells(i, 1) = s
ws.Cells(i, 4) = "D" & i
Next
MsgBox "done " & i - 1
End Sub
i have problem with my code in vba. I have to find how much similar numbers are in column 1 and 2, but for example Column 1 (6,6,34,21,23,40) and column2 (49,34,6,9,6,20) should write 3 cause there are pairs 6-6, 6-6 and 34-34. I know its messy explenation but i hope its understandable. My code so far is:
Sub totolotek()
Dim i As Integer
Dim x As Integer
Dim j As Integer
Dim liczba As Integer
Dim suma As Integer
Dim ileLosowan As Integer
Range("B2:C7").Interior.Color = RGB(135, 134, 125)
Range("B2:B7").Font.ColorIndex = 3
Range("C2:C7").Font.ColorIndex = 5
ileLosowan = 7
Randomize
For i = 2 To ileLosowan
x = Int(Rnd * (49) + 1)
Range("c" & i) = x
Next i
For i = 2 To 7
liczba = Range("c" & i)
For j = 2 To 7
liczbe = Range("b" & j)
If liczbe = liczba Then
Range("c" & i).Interior.Color = RGB(255, 255, 0)
Range("b" & j).Interior.Color = RGB(255, 255, 0)
suma = suma + 1
End If
Next j
Next i
Range("c" & 9) = suma
End Sub
Try this. I invested some time and I added some lines of code. The macro find all the number pairs.
Example (6,6,3,4,2) (2,3,6,9,0) --> results 3: (6-6, 3-3, 2-2)
Sub totolotek()
Dim i As Integer
Dim x As Integer
Dim j As Integer
Dim liczba As Integer
Dim suma As Integer
Dim ileLosowan As Integer
Dim str_B As String, str_C As String, str_BC As String
Dim max_rand As Long
ileLosowan = 20 ' you can change the number of element in the column
max_rand = 49 ' max randum number
start_row = 2 'start_row
str_BC = "B2:C" & ileLosowan
str_B = "B2:B" & ileLosowan
str_C = "C2:C" & ileLosowan
Range(str_BC).Interior.Color = RGB(135, 134, 125)
Range(str_B).Font.ColorIndex = 5
Range(str_C).Font.ColorIndex = 5
Randomize
For i = start_row To ileLosowan
x = Int(Rnd * (max_rand) + 1)
Range("C" & i) = x
Next i
For i = start_row To ileLosowan
x = Int(Rnd * (max_rand) + 1)
Range("B" & i) = x
Next i
liczba_array = Range("B" & start_row & ":B" & ileLosowan).Value2
liczbe_array = Range("C" & start_row & ":C" & ileLosowan).Value2
ReDim ID_array(1 To 1)
ID_array(1) = max_rand + 1
Count = 1
For i = 1 To UBound(liczba_array, 1)
For j = 1 To UBound(liczbe_array, 1)
For k = 1 To UBound(ID_array, 1)
If ID_array(k) = j Then
GoTo out
End If
Next k
If liczba_array(i, 1) = liczbe_array(j, 1) Then
Range("B" & (start_row + i - 1)).Interior.Color = RGB(150 + Count * 20, 0, 0)
Range("C" & (start_row + j - 1)).Interior.Color = RGB(150 + Count * 20, 0, 0)
suma = suma + 1
ID_array(Count) = j
Count = Count + 1
ReDim Preserve ID_array(1 To Count)
Exit For
End If
Next j
out:
Next i
Range("C" & ileLosowan + 2) = suma
End Sub
Something like this will do what you're after. Just incorporate it into you're code cause I don't really know what's going on there.
Dim i As Long, j As Long, arr As Variant, Total As Integer
For i = 2 To 7 'Rows to loop through in the column
Total = 0
arr = Split(Range("A" & i), ",") 'Split column A using the comma
For j = 0 To UBound(arr) 'Loop through the split values
If InStr(Range("B" & i), arr(j)) > 0 Then 'Find if value is within other column
Total = Total + 1 'If it is, add 1 to total
End If
Next j
Range("C" & i) = Total 'Write total to another column on same row
Next i
Or if you want a basic function for it that you can use in your sheet you can use this:
Public Function CountMatches(Cell As String, Rng As Range, Optional Delim As String)
Dim i As Long, j As Long, arr As Variant, Total As Integer
If Delim = "" Then Delim = ","
If Rng.Count > 1 Then
CountMatches = "Please choose 1 cell to compare to."
Exit Function
End If
Total = 0
arr = Split(Cell, Delim) 'Split column A using the comma
For j = 0 To UBound(arr) 'Loop through the split values
If InStr(Rng, arr(j)) > 0 Then 'Find if value is within other column
Total = Total + 1 'If it is, add 1 to total
End If
Next j
CountMatches = Total
End Function
Use it like =CountMatches(A1,B1,",")
I'm trying to simplify my code to dynamically check some values and update a bunch of tickboxes.
The tickboxes are sort of a table, their name is "col" & number_of_column & type_of_data
ie:
Col1PAM Col2PAM Col3PAM
Col1RL Col2RL Col3RL
I tried a simple approach with for...next which works:`
For i = 1 To 16
If ThisWorkbook.Sheets("Setup").Cells(j + 2, i + 1) = 1 Then
Me.Controls("Col" & i & "PAM").Value = True
Else: Me.Controls("Col" & i & "PAM").Value = False
End If
If ThisWorkbook.Sheets("Setup").Cells(j + 3, i + 1) = 1 Then
Me.Controls("Col" & i & "RL").Value = True
Else: Me.Controls("Col" & i & "RL").Value = False
End If
Next i
But I have a lot of column types and I tried to make the column type dynamic:
Dim Coltype1 As String
Dim coltype2 As String
Coltype1 = "PAM"
coltype2 = "RL"
For j = 1 To 2
For i = 1 To 16
If ThisWorkbook.Sheets("Setup").Cells(j + 2, i + 1) = 1 Then
Me.Controls("Col" & i & ("Coltype" & j)).Value = True
Else: Me.Controls("Col" & i & ("Coltype" & j)).Value = False
End If
Next i
Next j
My syntax is incorrect and after many tries, I can't figure out what would be a proper one. Any advice ?
On a side note, I also tried the for...next approach to declare my coltype1, coltype2... variables but it looks like you can't do that?
Thanks for any tips!
Something like this:
Dim arr(1 To 2) As String, ws As WorkSheet, i As Long, j As Long
Set ws = ThisWorkbook.Sheets("Setup")
arr(1) = "PAM"
arr(2) = "RL"
For j = 1 To 2
For i = 1 To 16
Me.Controls("Col" & i & arr(j)).Value = (ws.Cells(j + 2, i + 1) = 1)
Next i
Next j
I'm trying to do a calculation that will loop through multiple columns, the maximum would be 31 columns (31 days in a month).
Starting from "B8", next column would be "C8" ...
Excel template
I managed to calculate the first range.
I want to add a loop to calculate the number of hours for every existing column: Which could vary from 1 day to 31 days depending on the person using the excel template.
The number of projects could vary too "Code OTP" from 1 to 10 projects.
Update of my code:
Sub CalculHeuresTravail()
Application.ScreenUpdating = False
Dim i As Integer, firstDate As Date, secondDate As Date, n, rng As Range
Set ws = ThisWorkbook.Sheets("Feuil1")
MaSomme = 0
i = 8
f = 8
firstDate = ws.Range("E2")
secondDate = ws.Range("E3")
n = DateDiff("d", firstDate, secondDate)
n = n + 1
While ws.Range("A" & i).Value <> ""
i = i + 1
Wend
While f < i
MaSomme = MaSomme + ws.Range("B" & f).Value
f = f + 1
Wend
If MaSomme = "8,8" Then
MsgBox "OK"
Else: MsgBox "NON"
End If
End Sub
Here above is the solution that worked for me :
It loops through every column specified in a variable range stocked in a variable called 'e' that calculates the first column to start with and number of days specified by the user.
Sub CalculHeuresTravail()
Application.ScreenUpdating = False
Dim i As Integer, firstDate As Date, secondDate As Date, nombreDeJours, rng As Range, e
Set ws = ThisWorkbook.Sheets("Feuil1")
nombreDeProjets = 8
firstDate = ws.Range("E2")
secondDate = ws.Range("E3")
nombreDeJours = DateDiff("d", firstDate, secondDate)
nombreDeJours = nombreDeJours + 1
While ws.Range("A" & nombreDeProjets).Value <> ""
nombreDeProjets = nombreDeProjets + 1
Wend
IndiceDeColomne = 2
e = IndiceDeColomne + nombreDeJours
While IndiceDeColomne < e
caseDebutHeures = 8
MaSomme = 0
While caseDebutHeures < nombreDeProjets
MaSomme = MaSomme + ws.Cells(caseDebutHeures, IndiceDeColomne).Value
caseDebutHeures = caseDebutHeures + 1
ws.Cells(6, IndiceDeColomne).Value = MaSomme
Wend
If MaSomme = "8,8" Then
MsgBox "Colomne " & IndiceDeColomne & " OK"
Else: MsgBox "Colomne " & IndiceDeColomne & " NON OK"
End If
IndiceDeColomne = IndiceDeColomne + 1
Wend
End Sub