I am pulling a work organization report and want to find and filter by a unique ID value. The unique ID to be filtered is specified by a public property (this number is used on another occasion so that is why it is public) entered through a text box within a userform.
User enters unique ID of manager they want to filter under
Use unique ID to find which manager level column has unique ID
Move onto the next column if ID is not found
Once ID is found, Filter column
There are 9 different manager levels I am filtering through, columns AU, AW, AY, BA ,BC, BE, BG, BI, & BK, and they all rest on row 3. Therefore I have columns 'A3:BK3' but am only filtering between 'AU3:BK3' to pull data in the earlier columns.
++++++Open File Dialog:
```
Private Sub SelectButton_Click()
Dim SelectedFile As String
SelectedFile = Application.GetOpenFilename()
SelectedFiletxtbox = SelectedFile
End Sub
```
++++++Public Property Code:
```
Public Property Get OpenFileTxt() As String
OpenFileTxt = SelectedFiletxtbox.Value
End Property
```
++++++Execution Piece:
```
Private Sub EmailButton_Click()
'Workbooks.Open OpenFile
Application.ScreenUpdating = False
If Len(Trim(Me.EnterWWIDtxtbox.Text)) = 0 Then
Me.EnterWWIDtxtbox.SetFocus
MsgBox "Must provide a Unique ID"
Exit Sub
End If
'WWID = Trim(Me.EnterWWIDtxtbox.Text)
'Path to be pulled from open file dialog as reports are dynamic
Dim ws As Worksheet
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=OpenFileTxt)
Set ws = wb.Worksheets("Sheet1")
Dim aColumns() As String
aColumns = Split("AU,AW,AY,BA,BC,BE,BG,BI,BK", ",")
Dim bFound As Boolean
bFound = False
Dim rFound As Range
Dim vColumn As Variant
For Each vColumn In aColumns
Set rFound = ws.Columns(vColumn).Find(WWID, , xlValues, xlPart)
If Not rFound Is Nothing Then
bFound = True
MsgBox "Found [" & WWID & "] in column " & vColumn
With ws.Columns(vColumn)
.AutoFilter 1, rFound.Value
MsgBox "filtered"
'Do stuff with the filtered data here
End With
Exit For
End If
Next vColumn
If bFound = False Then MsgBox "Unique ID [" & WWID & "] not found"
'Filter by Region Selected
'Range("AG3").AutoFilter Field:=33, Criteria1:=Region
Unload DistrUserForm
'Open E-Mail
Application.ScreenUpdating = True
End Sub
```
I created a test workbook for this and filled it with junk data. I then created a basic userform that only had a textbox (named txtUniqueID) and a button (named CommandButton1). Entered the ID I was looking for in the textbox and clicked the button to run the search and filter if found. Verified it worked as intended. You should be able to adapt this to your needs. Here's the full userform code. Note the Dim WWID As Variant at the top outside of the sub since you said that was a public variable (this could also have been in a standard module and instead of Dim it would be Public, I just did this for ease of testing).
Dim WWID As Variant
Private Sub CommandButton1_Click()
If Len(Trim(Me.txtUniqueID.Text)) = 0 Then
Me.txtUniqueID.SetFocus
MsgBox "Must provide a Unique ID"
Exit Sub
End If
WWID = Trim(Me.txtUniqueID.Text)
'Explicitly define your workbook and worksheet where the data is
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim aColumns() As String
aColumns = Split("AU,AW,AY,BA,BC,BE,BG,BI,BK", ",")
Dim bFound As Boolean
bFound = False
Dim rFound As Range
Dim vColumn As Variant
For Each vColumn In aColumns
Set rFound = ws.Columns(vColumn).Find(WWID, , xlValues, xlPart)
If Not rFound Is Nothing Then
bFound = True
MsgBox "Found [" & WWID & "] in column " & vColumn
With ws.Columns(vColumn)
.AutoFilter 1, rFound.Value
MsgBox "filtered"
'Do stuff with the filtered data here
.AutoFilter 'Remove filter afterwards
End With
Exit For
End If
Next vColumn
If bFound = False Then MsgBox "Unique ID [" & WWID & "] not found"
End Sub
Related
I have a survey with health data from patients. I have a sheet with all the data named "data",
This is how the data sheet looks like, each column being some category from the patient (there are more rows):
I am creating a macro where the user has to select a Health Authority from a drop-down box, and that will create a new sheet named as the health authority selected. The button assigned to the macro is on another sheet called "user".
This is my code so far:
EDIT: I added sub demo () to try and paste it but it did not work. It says variable not defined in the part " With Sheets(sName)"
Option Explicit
Sub createsheet2()
Dim sName As String, ws As Worksheet
sName = Sheets("user").Range("M42").Value
' check if already exists
On Error Resume Next
Set ws = Sheets(sName)
On Error GoTo 0
If ws Is Nothing Then
' ok add
Set ws = Sheets.Add(after:=Sheets(Sheets.Count))
ws.Name = sName
MsgBox "Sheet created : " & ws.Name, vbInformation
Else
' exists
MsgBox "Sheet '" & sName & "' already exists", vbCritical, "Error"
End If
End Sub
Sub demo()
Const COL_HA = 6 ' F
Dim id As Long, rng As Range
id = 20 ' get from user dropdown
With Sheets("user")
.AutoFilterMode = False
.UsedRange.AutoFilter field:=COL_HA, Criteria1:=id
Set rng = .UsedRange.SpecialCells(xlVisible)
End With
' new sheet
'here is the problem
With Sheets(sName)
rng.Copy .Range("A1")
.Range("A1").Activate
End With
End Sub
I need to write the code that inserts in the new sheet only the data of the patients of the chosen Health Authority. Each Health Authority corresponds to a number
"sha" column is the health authority that the user previously selected.
Does anyone know how to insert the data I need to this new created sheet?
I think that I need to filter the data first and then paste it inside the sheet. I am very new at VBA and I'm lost.
Replace your code with this
Option Explicit
Sub createsheet()
Const COL_HA = 6 ' F on data sheet is Health Auth
Dim sName As String, sId As String
Dim wsNew As Worksheet, wsUser As Worksheet
Dim wsIndex As Worksheet, wsData As Worksheet
Dim rngName As Range, rngCopy As Range
With ThisWorkbook
Set wsUser = .Sheets("user")
Set wsData = .Sheets("data")
Set wsIndex = .Sheets("index")
End With
' find row in index table for name from drop down
sName = Left(wsUser.Range("M42").Value, 30)
Set rngName = wsIndex.Range("L5:L32").Find(sName)
If rngName Is Nothing Then
MsgBox "Could not find " & sName & " on index sheet", vbCritical
Else
sId = rngName.Offset(, -1) ' column to left
End If
' create sheet but check if already exists
On Error Resume Next
Set wsNew = Sheets(sName)
On Error GoTo 0
If wsNew Is Nothing Then
' ok add
Set wsNew = Sheets.Add(after:=Sheets(Sheets.Count))
wsNew.Name = sName
MsgBox "Sheet created : " & wsNew.Name, vbInformation
Else
' exists
MsgBox "Sheet '" & sName & "' already exists", vbCritical, "Error"
Exit Sub
End If
' filter sheet and copy data
Dim lastrow As Long, rngData As Range
With wsData
lastrow = .Cells(.Rows.Count, COL_HA).End(xlUp).Row
Set rngData = .Range("A10:Z" & lastrow)
.AutoFilterMode = False
rngData.AutoFilter Field:=COL_HA, Criteria1:=sId
Set rngCopy = rngData.SpecialCells(xlVisible)
.AutoFilterMode = False
End With
' new sheet
With wsNew
rngCopy.Copy .Range("A1")
.Range("A1").Activate
End With
MsgBox "Data for " & sId & " " & sName _
& " copied to wsNew.name", vbInformation
End Sub
I am pulling a work organization report and want to find and filter by a unique ID value. The unique ID to be filtered is specified by a public property (this number is used on another occasion so that is why it is public) entered through a text box within a userform. The file being used is a dynamically named report that the user selects from an open file dialog.
User enters unique ID of manager they want to filter under
Use unique ID to find which manager level column has unique ID
Move onto the next column if ID is not found
Once ID is found, Filter column
There are 9 different manager levels I am filtering through, columns AU, AW, AY, BA ,BC, BE, BG, BI, & BK, and they all rest on row 3. Therefore I have columns 'A3:BK3' but am only filtering between 'AU3:BK3' to pull data in the earlier columns.
Problem: I am continuing to receive a "Run-time error '1004': AutoFilter method of Range class failed" and I have no idea why, even after trying to debug. It works on some columns, but not on others when using test IDs that are throughout the 9 columns.
Code:
Private Sub EmailButton_Click()
'test WWIDS
'75305 -- 337431 -- 152820578 -- 152821156
Application.ScreenUpdating = False
'Filter by WWID -- Question: How to know who to pull for?
'Filter criteria (Unique ID - WWID), if it does not exist, then move to next, else end/stop
If Len(Trim(Me.EnterWWIDtxtbox.Text)) = 0 Then
Me.EnterWWIDtxtbox.SetFocus
MsgBox "Must provide a Unique ID"
Exit Sub
End If
Dim ws As Worksheet
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=OpenFileTxt)
Set ws = wb.Worksheets("Sheet1")
With wb.Worksheets("Sheet1")
Dim aColumns() As String
aColumns = Split("AU,AW,AY,BA,BC,BE,BG,BK,BI", ",")
Dim bFound As Boolean
bFound = False
Dim rFound As Range
Dim vColumn As Variant
For Each vColumn In aColumns
Set rFound = ws.Columns(vColumn).Find(WWID, , xlValues, xlPart)
If Not rFound Is Nothing Then
bFound = True
MsgBox "Found [" & WWID & "] in column " & vColumn
With ws.Columns(vColumn)
.AutoFilter 1, rFound.Value
End With
Exit For
End If
Next vColumn
If bFound = False Then MsgBox "Unique ID [" & WWID & "] not found"
End With
I'm new to VBA just FYI, I tackle problems to learn, but my answer may not be perfect.
TLDR:
Use: With ws.Range(rFound.Address(False, False)) NOT With ws.Columns(vColumn)
You have a bunch of repeating code which I tried to trim down, but as I'm not 100% on the end goal or how things work, I could only do so much. Here is what I ended up with.
Private Sub EmailButton_Click()
'Get WWID
WWID = "111"
'WWID = "777" ' HardCode for Testing
Dim ws As Worksheet
Dim wb As Workbook
Set wb = ActiveWorkbook
Set ws = wb.ActiveSheet
Dim aColumns() As String
aColumns = Split("AU,AW,AY,BA,BC,BE,BG,BI,BK", ",")
If WWID = "111" Then
Col = "47" 'AU = "47"
End If
AW = "49"
AY = "51"
BA = "53"
BC = "55"
BE = "57"
If WWID = "777" Then
Col = "59" 'BG = "59"
End If
BI = "61"
BK = "63"
ws.AutoFilterMode = False
Dim rFound As Range
Dim vColumn As Variant
For Each vColumn In aColumns
Set rFound = ws.Columns(vColumn).Find(WWID, , xlValues, xlPart)
If Not rFound Is Nothing Then
With ws.Range(rFound.Address(False, False))
.AutoFilter Col, rFound.Value
End With
End If
Next vColumn
End Sub
[table - worksheet "output - flat"][1]
I have code below that checks to see if column "NamedRange" in the table attached appears as a named range in the (dstRng) template and if it does exist it returns the value to the right ("report balance"). How can I add a condition where when the user chooses a template it will only return values based on the Ted ID - in the table attached. I have 2 templates and it loops through the two templates however I want the first template to only return values for Ted ID 10004 and template 2 it will only return values for Ted ID 11372 and etc. etc. Hope that makes sense... let me know if u have any questions
Option Explicit
Sub Button4_Click()
Dim Desktop As Variant
Dim Files As Object
Dim Folder As Variant
Dim oShell As Object
Dim Tmplts As Variant ' Templates folder
Dim wsLocal As Worksheet
Dim wsGroup As Worksheet
Dim wb As Object
' Check Box 2 "Select All" must be checked to run the macro.
If ActiveSheet.Shapes("Check Box 2").ControlFormat.Value = xlOff Then Exit Sub
Application.ScreenUpdating = False
Application.EnableEvents = False
' Prompt user to locate the Templates folder.
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = True Then
Tmplts = .SelectedItems(1)
Else
Exit Sub
End If
End With
Set oShell = CreateObject("Shell.Application")
Set Desktop = oShell.Namespace(0)
' Create the Output folder on the User's Desktop if it does not exist.
Set Folder = Desktop.ParseName("Output")
If Folder Is Nothing Then
Desktop.NewFolder "Output"
Set Folder = Desktop.ParseName("Output")
End If
Set Files = oShell.Namespace(Tmplts).Items
Files.Filter 64, "*.xlsm"
For Each wb In Files
Set wb = Workbooks.Open(Filename:=wb.Path, UpdateLinks:=False)
Call BreakLinks(wb)
On Error Resume Next
Set wsLocal = wb.Worksheets("RVP Local GAAP")
Set wsGroup = wb.Worksheets("RVP Group GAAP")
'unprotect workbook
wsLocal.Unprotect Password:="KqtgH5rn9v"
wsGroup.Unprotect Password:="KqtgH5rn9v"
On Error GoTo 0
' Check that both worksheets exist before updating.
If Not wsLocal Is Nothing And Not wsGroup Is Nothing Then
Call ProcessNamedRanges(wb)
'lock the workbook
wsLocal.Protect Password:="KqtgH5rn9v"
wsGroup.Protect Password:="KqtgH5rn9v"
''MsgBox "Ranges have been updated sucessfully."
' Save the workbook to the folder and close.
On Error Resume Next
wb.SaveAs Filename:=Folder.Path & "\" & wb.Name
ActiveWorkbook.Close True
On Error GoTo 0
End If
Next wb
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Sub ProcessNamedRanges(ByRef wb As Workbook)
Dim dstRng As Range
Dim rng As Range
Dim rngName As Range
Dim rngNames As Range
Dim wks As Worksheet
Set wks = ThisWorkbook.Sheets("Output - Flat")
' Exit if there are no named ranges listed.
If wks.Range("D4") = "" Then Exit Sub
Set rngNames = wks.Range("D4").CurrentRegion
Set rngNames = Intersect(rngNames.Offset(1, 0), rngNames.Columns(2))
'Loop through all the values in NamedRange
For Each rngName In rngNames
' Verify the Named Range exists.
On Error Resume Next
Set dstRng = wb.Names(rngName.Text).RefersToRange
If Err = 0 Then
'Copy the report balance to the Template worksheet in column "G".
dstRng.Value = rngName.Offset(0, 1).Value
Else
'answer = MsgBox("The Named Range """ & rngName.Value & """ Does Not Exist" & vbLf & vbLf & "Continue?", vbYesNo + vbExclamation)
'If answer = vbNo Then Exit Sub
End If
On Error GoTo 0
Next rngName
End Sub
Sub BreakLinks(ByRef wb As Workbook)
Dim i As Long
Dim wbLinks As Variant
wbLinks = wb.LinkSources(xlExcelLinks)
If Not IsEmpty(wbLinks) Then
For i = 1 To UBound(wbLinks)
ActiveWorkbook.BreakLink wbLinks(i), xlLinkTypeExcelLinks
Next i
End If
End Sub
Hi All I have an Excel macro to create a request file. Those request files are create from log data numbers which are listed in Sheet1. There is a replacement process I use here. Data from sheet2 (ColumnA) will replace the letters or strings I have in sheet1 that will left all the integers only and remove all text or strings in a log data numbers.
Example:
If I have H1PL12N0 once the macro executed it will become 12 only and create a request file as h1p-12.req with a value of either D or M. My macro is working. My only concern is instead of using Sheet1 I want to use TextBox.
Therefore no need to key-in or input log data numbers in sheet1 instead I will key-in or input it in a TextBox in my UserForm. I already tried to search same or related issue but I cannot find.
Did try assigning or set Textbox to myDataSheet which is Sheet1 but I got an error telling object required. I'm just new in VBA and trying to make my own macro. Hopefully you can help me , thank you in advance.
heres my code:
Private Sub CREATE_REQ_Click()
Dim myData As String
Dim myReplaceSheet As Worksheet
Dim myLastRow As Long
Dim myRow As Long
Dim myFind As String
Dim myReplace1 As String
Dim myReplace2 As String
Dim sExportFolder, sFN
Dim rArticleName As Range
Dim rDisclaimer As Range
Dim oSh As Worksheet
Dim oFS As Object
Dim oTxt As Object
If project_list.Text = "" Then
MsgBox "Please select a project! Thanks!"
GoTo a11
End If
If combo1.Value = "" Then
MsgBox "Please select input ! Thanks!"
GoTo a11
End If
If ListBox1.Text = "" Then
MsgBox "Please select the Block Name! Thanks!"
GoTo a11
End If
If TextBox1.Value = "" Then
MsgBox "Please Key-in folder address ! Thanks!"
GoTo a11
End If
'Specify name of Data sheet
Set myData = TextBox2
Set myReplaceSheet = Sheets("Sheet2")
myLastRow = myReplaceSheet.Cells(Rows.Count, "A").End(xlUp).Row
Application.ScreenUpdating = False
For myRow = 2 To myLastRow
myFind = myReplaceSheet.Cells(myRow, "A")
myReplace1 = myReplaceSheet.Cells(myRow, "B")
myDataSheet.Select
'Range("A2").Select
On Error Resume Next
'Do all replacements on column A of data sheet
Columns("A:A").Replace What:=myFind, Replacement:=myReplace1,
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False,
SearchFormat:=False, ReplaceFormat:=False
Next myRow
sExportFolder = TextBox1 ' "D:\TEST\REQ_FILES_CREATED_HERE"
Set oSh = Sheet1
Set oFS = CreateObject("Scripting.Filesystemobject")
For Each rArticleName In oSh.UsedRange.Columns("A").Cells
'Set rDisclaimer = combo1.Value.Select 'rArticleName.Offset(, 1)
If Not (rArticleName = "" Or rArticleName = "LOG DATA") Then
'Add .txt to the article name as a file name
sFN = "-" & rArticleName.Value & ".req"
Set oTxt = oFS.OpenTextFile(sExportFolder & "\" & ListBox1 & sFN, 2, True)
oTxt.Write combo1.Value
oTxt.Close
End If
Next
'Reset error checking
On Error GoTo 0
Application.ScreenUpdating = True
MsgBox "REQUEST FILES CREATED!"
a11:
End Sub
I have a code that asks the user to select a sheet by writing its name in an inputbox, and then I need to check if the selected name is correct.
How can I write the "if" statement so to return back to the inputbox?
I'm using MS Word in Windows 7. This is the code:
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
Sub OpenExcelFile()
Dim oExcel As Excel.Application
Dim oWB As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim oneRange As Excel.Range
Dim aCell As Excel.Range
Dim intChoice As Integer
Dim strPath As String
Dim uiSheet As String
Set oExcel = New Excel.Application
'Select the start folder
Application.FileDialog(msoFileDialogOpen _
).InitialFileName = ActiveDocument.path
'Remove all other filters
Call Application.FileDialog(msoFileDialogOpen).Filters.Clear
'Add a custom filter
Call Application.FileDialog(msoFileDialogOpen).Filters.Add( _
"Only Excel File Allowed", "*.xl*")
'only allow the user to select one file
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogOpen).Show
'determine what choice the user made
If intChoice <> 0 Then
'get the file path selected by the user
strPath = Application.FileDialog( _
msoFileDialogOpen).SelectedItems(1)
End If
'open excel file and select sheet
Set oWB = oExcel.Workbooks.Open(strPath)
Dim strBuild As String
'set Array for user input control
Dim myArray() As Variant
ReDim myArray(1 To oWB.Sheets.Count)
'populate input box and array
For Each xlSheet In oWB.Worksheets
strBuild = strBuild & xlSheet.Name & vbCrLf
For i = 1 To oWB.Sheets.Count
myArray(i) = oWB.Sheets(i).Name
Next i
Next xlSheet
'show inputbox with list of sheets
strBuild = Left$(strBuild, Len(strBuild) - 2)
uiSheet = InputBox("Provide a sheet name." & vbNewLine & strBuild)
'check if User input match with sheet name
If IsInArray(uiSheet, myArray) Then
'show excel window
oExcel.Visible = True
'sort selected sheet by first column range
oExcel.Worksheets(uiSheet).Activate
Set oneRange = oExcel.Range("A1:A150")
Set aCell = oExcel.Range("A1")
oneRange.Sort Key1:=aCell, Order1:=xlAscending, Header:=xlYes
Else
MsgBox "Please enter a valid name!", vbCritical
End If
End Sub
If you replace the code starting with uiSheet = InputBox(..... with the code below, it should work.
'check if User input match with sheet name
Dim bSheetPresent As Boolean
bSheetPresent = False
Do Until bSheetPresent
uiSheet = InputBox("Provide a sheet name." & vbNewLine & strBuild)
If uiSheet = "" Then Exit Do
If IsInArray(uiSheet, myArray) Then
bSheetPresent = True
Else
MsgBox "Please enter a valid name!", vbCritical
End If
Loop
If bSheetPresent Then
'show excel window
oExcel.visible = True
'sort selected sheet by first column range
oExcel.Worksheets(uiSheet).Activate
Set oneRange = oExcel.Range("A1:A150")
Set aCell = oExcel.Range("A1")
oneRange.Sort Key1:=aCell, Order1:=xlAscending, Header:=xlYes
End If
If the user presses cancel on the inputbox, the it will exit the loop.
You may also consider to build a form with a pre-filled combobox. That way the user cannot make a mistake.
To create create your own inputbox with a list of sheets, you can do this:
Create a userform in the VBE
Name it frmSelectSheet
Put a combobox on it named cbSheets
Add the following code to the userform's code pane:
Private Sub UserForm_Initialize()
Dim oSheet As Worksheet
For Each oSheet In ThisWorkbook.Sheets
Me.cbSheets.AddItem oSheet.Name
Next oSheet
End Sub
Private Sub cbSheets_Change()
Me.Hide
End Sub
Add a module and add the following code to it:
Public Function SheetInputBox() As String
Dim ofrmSheetInput As New frmSelectSheet
ofrmSheetInput.Show
SheetInputBox = ofrmSheetInput.cbSheets
Unload ofrmSheetInput
End Function
Call the function like this
? SheetInputBox or uiSheet = SheetInputBox