I'm trying to find a solution for the following problem:
I have a sheet containing information on several customers with several projects each. The combiniation of customer + projectname is unique.
On a different sheet I want to be able to:
select the customer from a dynamic dropdown-list without duplicates (I have managed that)
then be presented with a second dropdown, reduced to only those projects of the selected customer
have the information in cells (C5:C7) filled automatically
As the data-sheets content is dynmaic and will contain lots of data, named tables are no option.
I'd be grateful I anyone had an idea on how to solve the problem!
It can be achieved through VBA. I have written the below code and worked for me.
Input sheet:
Try the below code.
Sub CustomerAndProject()
Dim Customer As String, Project As String, Info1 As String, Info2 As String, Info3 As String
Dim TotalCustomers As Integer, m As Integer
m = 1
'Get Total customers
TotalCustomers = Worksheets("Sheet1").Range("A1").End(xlDown).Row
'First loop to pick customers
For i = 2 To TotalCustomers
Customer = Worksheets("Sheet1").Range("A" & i).Value
'Second loop to pick the projects related to customer
For k = 2 To TotalCustomers
Project = Worksheets("Sheet1").Range("B" & k).Value
'Function r=to validate the duplicate customers and projects
If CustomerValidationForDuplication(Project, Customer, TotalCustomers) = False Then
'Third loop to pick and paste info data related to customer and project
For j = 2 To TotalCustomers
If Worksheets("Sheet1").Range("A" & j).Value = Customer And Worksheets("Sheet1").Range("B" & j).Value = Project Then
Worksheets("Sheet2").Cells(1, m).Value = Customer
Worksheets("Sheet2").Cells(2, m).Value = Project
If IsEmpty(Worksheets("Sheet1").Range("C" & j).Value) Then
Else: Info1 = Worksheets("Sheet1").Range("C" & j).Value
Worksheets("Sheet2").Cells(3, m).Value = Info1
End If
If IsEmpty(Worksheets("Sheet1").Range("D" & j).Value) Then
Else: Info2 = Worksheets("Sheet1").Range("D" & j).Value
Worksheets("Sheet2").Cells(4, m).Value = Info2
End If
If IsEmpty(Worksheets("Sheet1").Range("E" & j).Value) Then
Else: Info3 = Worksheets("Sheet1").Range("E" & j).Value
Worksheets("Sheet2").Cells(5, m).Value = Info3
End If
End If
Next
m = m + 1
End If
Next
Next
End Sub
Function CustomerValidationForDuplication(ProjectToBeVerified As String, CustomerToBeVerified As String, TotalCustomers As Integer) As Boolean
For l = 1 To TotalCustomers
If ProjectToBeVerified = Worksheets("Sheet2").Cells(2, l) Then
For m = 1 To TotalCustomers
If CustomerToBeVerified = Worksheets("Sheet2").Cells(1, m) Then
CustomerValidationForDuplication = True
Exit For
Else
CustomerValidationForDuplication = False
End If
Next
Else
CustomerValidationForDuplication = False
End If
If CustomerValidationForDuplication = True Then Exit For
Next
End Function
Output sheet:
Let me know if it works for you.
Note: I am new to VBA so my code won't be friendly. Edits are welcome.
Related
I've tried for a while to find (search) a solution to this but can't seem to.
I'm trying to read a list from an excel document, and based on the "country" item (which is selected on another combobox) filter the list. If it is the right country I want to add the row (4 items) to the combobox row.
I can't use a array because the length changes by country, and since only the second dimension of the array can be dynamic it populates the list backwards.
I currently get this error:
Assignment to constant not permitted.
The code:
Private Sub P_Country_Change()
Dim LastR As Integer
LastR = ActiveWorkbook.Worksheets("M_DB").Range("A2", Worksheets("M_DB").Range("A2").End(xlDown)).Rows.Count
Dim j As Integer
j = 0
For i = 2 To LastR
If ActiveWorkbook.Worksheets("M_DB").Range("E" & i).Value = P_Country.Value Then
With Press_m
.AddItem = ActiveWorkbook.Worksheets("M_DB").Range("A" & i).Value
.List(j, 1) = ActiveWorkbook.Worksheets("M_DB").Range("B" & i).Value
.List(j, 2) = ActiveWorkbook.Worksheets("M_DB").Range("C" & i).Value
.List(j, 3) = ActiveWorkbook.Worksheets("M_DB").Range("D" & i).Value
End With
j = j + 1
End If
Next i
End Sub
Thanks for your help!
Ok, so I made it work. I'm not sure exactly what I did right, but to help anyone else using this as a referenace, one thing I did that may have been it was set the properties of the combobox to:
locked = False
Also I changed the code a little bit, but not so much, here it is now:
Private Sub P_Country_Change()
Dim LastR As Integer
LastR = ActiveWorkbook.Worksheets("M_DB").Range("A2", Worksheets("M_DB").Range("A2").End(xlDown)).Rows.Count
Dim j As Integer
j = 0
For s = P_m.ListCount - 1 To 0 Step -1
P_m.RemoveItem s
Next s
With P_m
.ColumnCount = 4
.ColumnWidths = "125;125;125;125"
.ColumnHeads = False
End With
For i = 2 To LastR
If ActiveWorkbook.Worksheets("M_DB").Range("E" & i).Value = Press_Country.Value Then
P_m.AddItem ActiveWorkbook.Worksheets("M_DB").Range("B" & i).Value ' Name
P_m.List(j, 1) = ActiveWorkbook.Worksheets("M_DB").Range("C" & i).Value ' Corporation
P_m.List(j, 2) = ActiveWorkbook.Worksheets("M_DB").Range("D" & i).Value ' Province
P_m.List(j, 3) = ActiveWorkbook.Worksheets("M_DB").Range("E" & i).Value ' City
j = j + 1
End If
Next i
End Sub
Finally, I found a great referance here. teach me right? RTFM first ;-)
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
Could someone help me out with the following code, I thought i figured it out but keep on stranding with the same problem:
Sub history()
nsheets = ActiveWorkbook.Worksheets.Count 'count sheets in workbook
nas_index = ActiveSheet.Index 'index of the activated sheet
nas_LR = Sheets(nas_index).Cells(Sheets(nas_index).Rows.Count, "A").End(xlUp).Row 'count rows of activesheet
For d = 1 To nsheets
If d < nas_index Then
pre_index = Sheets(nas_index - d).Index
pre_LR = Sheets(pre_index).Cells(Sheets(pre_index).Rows.Count, "A").End(xlUp).Row
oldtime = Sheets(d).Cells(1, 6).Value
newwknr = Sheets(nas_index).Cells(1, 7).Value
oldwknr = Sheets(pre_index).Cells(1, 7).Value
StrOldTime = Format(oldtime, "hh:mm:ss")
For n = 3 To nas_LR
prid_new = Sheets(nas_index).Cells(n, 1).Value
For o = 3 To pre_LR
prid_old = Sheets(pre_index).Cells(o, 1).Value
pre_am = Sheets(pre_index).Cells(o, 6).Value
pre_amw = CStr(pre_am) & "(" & StrOldTime & ")" & "(wk: " & oldwknr & ")"
If prid_new = prid_old Then
'Below is not working properly
'------------------------------
re = re & " " & pre_amw
Sheets(nas_index).Cells(n, 10).Value = re
'------------------------------
End If
Next o
Next n
Else
'MsgBox exit loop
Exit For
End If
Next d
'------------------nevermind below
Dim ntime As Date, nStrTime As String
If Not ThisWorkbook.ActiveSheet.Cells(1, 10).Value = "" Then
'-new time
ThisWorkbook.ActiveSheet.Cells(1, 12).Value = Time()
ntime = ThisWorkbook.ActiveSheet.Cells(1, 12).Value
mstrtime = Format(ntime, "hh:mm:ss:ms")
ThisWorkbook.ActiveSheet.Cells(1, 12).Value = mstrtime
'-old time
gettime = ThisWorkbook.ActiveSheet.Cells(1, 10).Value
ThisWorkbook.ActiveSheet.Cells(1, 11).Value = gettime
myStrTime = Format(gettime, "hh:mm:ss:ms")
ThisWorkbook.ActiveSheet.Cells(1, 11).Value = myStrTime
End If
End Sub
The image below is so far what I got (the text in red, is what i wish to have).
My goal is to have the following Check if I bought the same item before (ID). Collect data of this ID and store it in the column History. So that I can see if the product has been price changed over the previous weeks. I can't get the data properly of previous sheets. Instead of getting the following:
item: A B C D or
item: D C B A
I get something like this:
item: A A A A A A B B B B B B C C C C C C D D D D D D or
item: A B C D A B C D A B C D
I think I am failing here:
If prid_new = prid_old Then
'Below is not working properly
'------------------------------
re = re & " " & pre_amw
Sheets(nas_index).Cells(n, 10).Value = re
'------------------------------
End If
Can someone lent me a hand.
I tried looping the worksheets within a grocery item loop with some success.
Historical data is gathered from every worksheet prior to the current worksheet (ActiveSheet) onto the current worksheet.
Option Explicit
Sub costHistory()
Dim i As Long, w As Long, gro As Long, ndx As Long, g As Variant
Dim icost As Double, lcost As Double, dif As String
With ActiveSheet
ndx = ActiveSheet.Index
For i = 3 To .Cells(.Rows.Count, "A").End(xlUp).Row
gro = .Cells(i, "A").Value2
lcost = .Cells(i, "D").Value2
dif = vbNullString
For w = 1 To ndx - 1
With Worksheets(w)
g = Application.Match(gro, .Columns(1), 0)
If Not IsError(g) Then
If .Cells(g, "D").Value2 <> lcost Then
dif = Format(.Cells(g, "D").Value2, "0.00") & _
Format(.Cells(g, "F").Value2, " 0 ") & _
Format(.Cells(1, "F").Value2, "(hh:mm:ss)") & _
Format(.Cells(1, "G").Value2, " (\w\k\:0)") & _
Chr(124) & dif
End If
End If
End With
Next w
If CBool(Len(dif)) Then
.Cells(i, "J") = Left(dif, Len(dif) - 1)
End If
Next i
End With
End Sub
I have an excel document that is, and looks physically like a report. I only need some of the data. What is the best of coming up with a formula that gets me this information. Document has 88 entries.
You can click the image for a full-size version:
I want to come up with a search that returns the stuff in yellow. Any idea how to get that done? Or is this a manual search type of deal? I'm asking, not because I want to save 3 hours on doing this, but because I would like to save time in the future. Thanks!
As long as your template is in the same format, the below code should work. I tried to keep it as simple as possible so you can see what the individual steps do. You an adjust the columns where the data is pasted to suit. You will need to first create a sheet called 'Extract' and change any occurrence of 'YourSheetNameHere' within the code.
Sub Extract()
Dim Page, Company, Num, Name, ProjMan, TotalVal, Fee As String
Dim r, c As Integer
c = 1
Sheets("YourSheetNameHere").Select
For r = 1 To 4680
If Left(Range("J" & r).Value, 4) = "Page" Then
'Stores the values
Page = Range("J" & r)
ProjMan = Range("J" & r + 2)
TotalVal = Range("J" & r + 4)
Company = Range("J" & r + 4)
Num = Range("J" & r + 6)
Name = Range("J" & r + 7)
Fee = Range("H" & r + 31)
'Pastes the values in a new sheet called Extract (which you will need to create first)
Sheets("Extract").Select
Range("A" & c) = Page
Range("B" & c) = ProjMan
Range("C" & c) = TotalVal
Range("D" & c) = Company
Range("E" & c) = Num
Range("F" & c) = Name
Range("G" & c) = Fee
c = c + 1
Sheets("YourSheetNameHere").Select 'You will need to adjust to suit
End If
Next r
End Sub
I'm trying to write an if function into a save button on a user-form so that if the data entered into the user-form is already on sheet 2 then it only gets written to sheet 1. But if it does not exist on sheet 2 then the data from the user-form gets written to both sheet 1 and sheet 2. This is because I want the data on sheet 2 to act like a sort of database and obviously do not want duplicates. I've made the write procedures into two separate modules (I figured this would make it easier to differentiate). Here is my code (Be gentle I'm still learning)
Sub writetosheet1()
Dim i As Integer
i = 1
While ThisWorkbook.Worksheets("Sheet1").Range("A" & i).Value <> ""
i = i + 1
Wend
ThisWorkbook.Worksheets("Sheet1").Range("a" & i).Value = UserForm1.txt1.Value
ThisWorkbook.Worksheets("Sheet1").Range("b" & i).Value = UserForm1.txt2.Value
ThisWorkbook.Worksheets("Sheet1").Range("c" & i).Value = UserForm1.txt3.Value
ThisWorkbook.Worksheets("Sheet1").Range("d" & i).Value = UserForm1.txt4.Value
ThisWorkbook.Worksheets("Sheet1").Range("e" & i).Value = UserForm1.txt5.Value
End Sub
Sub writetosheet2()
Dim i As Integer
i = 1
While ThisWorkbook.Worksheets("Sheet1").Range("A" & i).Value <> ""
i = i + 1
Wend
ThisWorkbook.Worksheets("Sheet2").Range("a" & i).Value = UserForm1.txt1.Value
ThisWorkbook.Worksheets("Sheet2").Range("b" & i).Value = UserForm1.txt2.Value
ThisWorkbook.Worksheets("Sheet2").Range("c" & i).Value = UserForm1.txt4.Value
ThisWorkbook.Worksheets("Sheet2").Range("d" & i).Value = UserForm1.txt5.Value
End Sub
Private Sub CMDSAVE_Click()
Dim id As Long
id = txt1.Value
If id <> Sheets("Sheet2").Range("a:a").Value Then
Call writetosheet1
Call writetosheet2
Else
Call writetosheet1
End If
End Sub
Any help on this would be fantastic! Thanks.
I think that you can not compare one single value with whole range like this:
If id <> Sheets("Sheet2").Range("a:a").Value Then
You need to go trough all cells in that range separately.
If Application.CountIf(Sheet2.Range("A:A"), id) > 0 then
'write only to sheet1
else
'write to both sheets
end if