List found strings on sheet

G

GS

Better yet...

Sub FindSheetsWithID_v4()
' Looks for an ID on all sheets with search tag,
' and outputs results to summary sheet named "Instructions".
' Note: The search tag is a local scope defined name range
' that contains the search data column address.

Dim Wks As Worksheet, wksTarget As Worksheet, rng As Range
Dim sID$, sOut$, sAddr1$
Dim bFoundID As Boolean, lCount&, vDataOut

sID = InputBox("Enter a Client ID")
If Trim(sID) = "" Then Exit Sub

'If we got here then initialize sOut
sOut = sID
Const sRngToSearch$ = "MyTag" '//edit to suit

On Error GoTo Cleanup
Set wksTarget = ThisWorkbook.Sheets("Instructions")
wksTarget.Activate '//to view results

For Each Wks In ThisWorkbook.Worksheets
'Comment out next line to include all sheets
If bNameExists(sRngToSearch, Wks) Then
sOut = sOut & "," & Wks.Name & "=": sAddr1 = ""
With Wks.Range(sRngToSearch)
Set rng = .Find(What:=sID, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns)
If Not rng Is Nothing Then
sAddr1 = rng.Address: bFoundID = True
End If
If bFoundID Then
Do
lCount = lCount + 1: Set rng = .FindNext(rng)
Loop While Not rng Is Nothing And rng.Address <> sAddr1
End If 'bFoundID
End With 'Wks.Range(sRngToSearch)
sOut = sOut & lCount: lCount = 0

'Comment out next line to include all sheets
End If 'bNameExists
Next 'Wks

'Output to worksheet
vDataOut = Split(sOut, ",")
'Next line assumes 1st row contains headings,
'or data already exists.
With wksTarget.Cells(Rows.Count, "A").End(xlUp)(2)
.Resize(1, UBound(vDataOut) + 1) = vDataOut
End With

Cleanup:
Set wksTarget = Nothing: Set rng = Nothing
End Sub

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
L

L. Howard

Note that for this v3 code to work on all sheets, the defined name

*must exist* on all sheets!

I think I need to back up a bit and restate where I am with all these codes.

This code below does EXACTLY what I am looking for with the exception of instead of an InputBox I want the code to go to the column G lists on each sheet (but not sheet "Instructions") and process the entries with a single click of the button.

Howard

Sub FindSheets_X()

Dim wsh As Worksheet, c As Range

Dim strID As String, strOut As String
Dim LRow As Long

strID = InputBox("Enter a Client ID numbet")
If Trim(strID) = "" Then Exit Sub

For Each wsh In ThisWorkbook.Sheets
If Not wsh.Name = "Instructions" Then
Set c = wsh.UsedRange.Find(What:=strID, _
LookIn:=xlValues, _
LookAt:=xlWhole)
If Not c Is Nothing Then

strOut = strOut & wsh.Index & ", "

End If
End If
Next

With Sheets("Instructions")
LRow = .Cells(Rows.Count, "A").End(xlUp).Row

If Len(strOut) > 0 Then
.Range("A" & LRow + 1) = strID
.Range("B" & LRow + 1) = Left(strOut, Len(strOut) - 2)
Else
.Range("A" & LRow + 1) = strID
.Range("B" & LRow + 1) = "Not found"
End If
End With

End Sub
 
G

GS

Like I asked before.., how/where does the code find/get the IDs to
search for? IOW, (1st & foremost) they must be available to code by
some method!

Also, you've reverted back to using UsedRange which will take longer
depending on its size. Meanwhile, I've been working toward something
more 'reliable' for results from entering only 1 ID. Not a problem to
do several IDs using arrays, but I recommend a 2D output array to
avaoid limitations of the Transpose() function (should that happen)!

I like the idea of giving the search range a local defined name because
if its RefersTo uses absolute refs then its location auto-adjusts when
columns are inserted/deleted. That means it doesn't need to be the same
column index on every sheet being searched, AND the search can be
limited to only sheets with that named range!

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
C

Claus Busch

Hi Howard,

Am Thu, 26 Jun 2014 10:41:27 -0700 (PDT) schrieb L. Howard:
This code below does EXACTLY what I am looking for with the exception of instead of an InputBox I want the code to go to the column G lists on each sheet (but not sheet "Instructions") and process the entries with a single click of the button.

please have a look:
https://onedrive.live.com/?cid=9378...#cid=9378AAB6121822A3&id=9378AAB6121822A3!326
for "FindSheets"

In sheet "Instructions" you write in A1:An your IDs to search. Then
press button, The sheets indices will be written in column B


Regards
Claus B.
 
G

GS

Hi Howard,
Am Thu, 26 Jun 2014 10:41:27 -0700 (PDT) schrieb L. Howard:


please have a look:
https://onedrive.live.com/?cid=9378...#cid=9378AAB6121822A3&id=9378AAB6121822A3!326
for "FindSheets"

In sheet "Instructions" you write in A1:An your IDs to search. Then
press button, The sheets indices will be written in column B


Regards
Claus B.

Claus,
Your example assumes that "Instructions" contains no instructions,
which is why I asked Howard to state where/how code gets the IDs. Also,
the sample doesn't split the results to separate columns which (I
believe) Howard wants done.

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
L

L. Howard

Claus,

Your example assumes that "Instructions" contains no instructions,

which is why I asked Howard to state where/how code gets the IDs. Also,

the sample doesn't split the results to separate columns which (I

believe) Howard wants done.
Hi Garry, Claus,

I believe the name of the sheet "Instructions" is a poor choice. May be better served to consider that name the same as "Summary" or "mySheet" and not a sheet to look to for "How to..."

The OP may indeed intend to use it as a formal Instructions sheet, but I am considering it simple a sheet with a name where the results go.

Claus, your last suggestion looks to me like it gets it done. It is not a loop through all the columns G on each search sheet but the results are certainly positive.

Garry, Id like to try you last suggestion, but am lost as to what or how that named range should look like.

Howard
 
G

GS

Garry, Id like to try you last suggestion, but am lost as to what or
how that named range should look like.

This v5 uses a comma delimited list stored in a cell named "IdList" on
"Instructions". It creates an array of arrays for all IDs listed on the
'tagged' sheets, then converts that to a 1-based 2D array to 'dump'
into "Instructions" on the next empty row.

Note that any all-numeric IDs return as numeric data (not as text) and
so requires formatting ColA if you want the results for numeric IDs
displayed as text. Complete code follows..



Sub FindSheetsWithID_v5()
' Looks for an ID on all sheets with search tag,
' and outputs results to summary sheet named "Instructions".
' Note: The search tag is a local scope defined name range
' that contains the search data column address.

Dim Wks As Worksheet, wksTarget As Worksheet, rng As Range
Dim sID$, sOut$, sAddr1$, lCount&, n&, vData

Const sRngToSearch$ = "MyTag" '//edit to suit

Set wksTarget = ThisWorkbook.Sheets("Instructions")
'Assume comma delimited ID list stored in named range
With wksTarget
.Activate: sID = .Range("IdList").Text
End With
If Trim(sID) = "" Then Exit Sub

On Error GoTo Cleanup
vData = Split(sID, ","): ReDim vDataOut(UBound(vData))
For n = LBound(vData) To UBound(vData)
sOut = vData(n): sID = sOut
For Each Wks In ThisWorkbook.Worksheets
If bNameExists(sRngToSearch, Wks) Then
sOut = sOut & "," & Wks.Name & "=": sAddr1 = ""
With Wks.Range(sRngToSearch)
Set rng = .Find(What:=sID, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns)
If Not rng Is Nothing Then
sAddr1 = rng.Address
Do
lCount = lCount + 1: Set rng = .FindNext(rng)
Loop While Not rng Is Nothing And rng.Address <> sAddr1
End If 'Not rng Is Nothing
End With 'Wks.Range(sRngToSearch)
sOut = sOut & lCount: lCount = 0
End If 'bNameExists
Next 'Wks
vDataOut(n) = Split(sOut, ",")
Next 'n

'Output to worksheet
Xform_1DimArrayOfArraysTo2D vDataOut
With wksTarget.Cells(Rows.Count, "A").End(xlUp)(2)
.Resize(UBound(vDataOut), UBound(vDataOut, 2)) = vDataOut
.EntireColumn.NumberFormat = "@"
End With


Cleanup:
Set wksTarget = Nothing: Set rng = Nothing
End Sub

Function bNameExists(sName$, oSource) As Boolean
' Checks if sName exists in oSource
' Arguments:
' sName The defined name to check for
' oSource A ref to the Wkb or Wks being checked
' Returns:
' True if name exists

Dim x As Object
On Error Resume Next
Set x = oSource.Names(sName): bNameExists = (Err = 0)
End Function

Sub Xform_1DimArrayOfArraysTo2D(Arr())
' Restructures a 1D 0-based dynamic array of arrays to a fixed 2D
1-based array
' Arguments:
' Arr() The array of arrays to be converted
'
Dim v1, vTmp(), lMaxCols&, lMaxRows&, n&, k&

If VarType(Arr) < vbArray Then Exit Sub

lMaxRows = UBound(Arr) + 1: vTmp = Arr: Erase Arr
'Get size of Dim2
For n = LBound(vTmp) To UBound(vTmp)
k = UBound(vTmp(n))
lMaxCols = IIf(k + 1 > lMaxCols, k + 1, lMaxCols)
Next 'n

ReDim Arr(1 To lMaxRows, 1 To lMaxCols)
For n = LBound(vTmp) To UBound(vTmp)
For k = LBound(vTmp(n)) To UBound(vTmp(n))
Arr(n + 1, k + 1) = vTmp(n)(k)
Next 'k
Next 'n
End Sub

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
L

L. Howard

Hi Garry,

This IdList has me stumped. I am not understanding how to make that list.


.Activate: sID = .Range("IdList").Text

Once it exists, I presume it holds all the items that are to be looked up on all the sheets. So instead of looping through the columns G on each sheet, the code can refer to the elements within that named range for the search items??

Howard
 
G

GS

Hi Garry,
This IdList has me stumped. I am not understanding how to make that
list.


.Activate: sID = .Range("IdList").Text

Once it exists, I presume it holds all the items that are to be
looked up on all the sheets. So instead of looping through the
columns G on each sheet, the code can refer to the elements within
that named range for the search items??

Howard

In A1 on "Instructions":
Type abc123,def456,ghi789

In the namebox (left of FormulaBar):
With A1 selected:
Type instructions!IdList and hit 'Enter'

Run the code as posted if you've added named ranges for the search
columns. Otherwise, add those names on each sheet that contains search
data, then run the code. Optionally (not recommended), modify the code
to use UsedRange.

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
G

GS

To name the search cols on each sheet...

Select the col

In the namebox type
'sheet name'!MyFlag
(or whatever name you want to use)
hit the 'Enter' key

...and be sure to update the const value in the code to match whatever
name you use.

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
L

L. Howard

Hi Garry,

Unable to make the name ranges work for me so I put this together which pretty much does what I want.

Problem I have with this code is I want to consider the columns have headers on all the G columns and the A and B column in sheet Instructions.

The code lines I have commented out work ok without respect to headers and the code below the commented lines throw an error.

Can't figure why I can't use Range("G2:G" & Cells(Rows.Count, 7).End(xlUp).Row) instead of G:G.

Howard


Sub G_Columns_To_One_Array()

Dim iRet As Integer
Dim strPrompt As String
Dim strTitle As String

' Promt
strPrompt = " Do you want to clear Columns A and B " & vbCr & vbCr & _
" and process another set of Data?"

' Dialog's Title
strTitle = "Sheet Finder"

'Display MessageBox
iRet = MsgBox(strPrompt, vbYesNo, strTitle)

' Check pressed button
If iRet = vbNo Then
MsgBox "Okay, Good bye"
Exit Sub
Else
MsgBox "Yes! Let'er Rip!"
Sheets("Instructions").Range("A:B").ClearContents
End If


Dim lastRow As Long, lastRowDest As Long
Dim varSheets As Variant
Dim varOut As Variant
Dim i As Integer

Application.ScreenUpdating = False

varSheets = Array("Sheet2", "Sheet3")
lastRowDest = 1

For i = LBound(varSheets) To UBound(varSheets)
With Sheets(varSheets(i))
lastRow = .Range("G" & Rows.Count).End(xlUp).Row
varOut = .Range("G2:G" & lastRow)
Sheets("Instructions").Cells(lastRowDest, 1) _
.Resize(rowsize:=lastRow) = varOut
lastRowDest = Sheets("Instructions").Range("A" & Rows.Count) _
.End(xlUp).Row + 1
End With
Next

Find_What_Sheet
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub

Sub Find_What_Sheet()

Dim c As Range, wsh As Worksheet
Dim strID As String, strOut As String
Dim LRow As Long, i As Long
Dim arrID As Variant

With Sheets("Instructions")
LRow = .Cells(Rows.Count, 1).End(xlUp).Row

'arrID = .Range("A1:A" & LRow) '/ maybe here?
arrID = .Range("A2:A" & LRow)

End With


For i = LBound(arrID) To UBound(arrID)
strOut = ""
For Each wsh In ThisWorkbook.Sheets
If wsh.Name <> "Instructions" Then
With wsh

'Set c = .Range("G:G").Find(What:=arrID(i, 1), _
LookIn:=xlValues, _
LookAt:=xlWhole)

'arrID(i, 1) = error 2042
Set c = .Range("G2:G" & Cells(Rows.Count, 7).End(xlUp).Row).Find(What:=arrID(i, 1), _
LookIn:=xlValues, _
LookAt:=xlWhole)

If Not c Is Nothing Then
strOut = strOut & Replace(wsh.Name, "Sheet", "") & ", "
End If
End With
End If
Next

With Sheets("Instructions")
If Len(strOut) > 0 Then
.Cells(i, 2) = Left(strOut, Len(strOut) - 2)
Else
.Cells(i, 2) = "Not found"
End If
End With
Next
End Sub
 
G

GS

Unable to make the name ranges work for me...

This is pretty much a basic fundamental of VBA programming and so I
urge you to persist with patience! said:
Problem I have with this code is I want to consider the columns have
headers on all the G columns and the A and B column in sheet
Instructions.

Find() doesn't care about headers!
The code lines I have commented out work ok without respect to
headers and the code below the commented lines throw an error.

Can't figure why I can't use Range("G2:G" & Cells(Rows.Count,
7).End(xlUp).Row) instead of G:G.

I sent you my test file. Have a look at how names are used/work with
the v5 code I last posted here.

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
G

GS

Final version follows for anyone interested...


Sub FindSheetsWithID_v6()
' Looks for an ID on all sheets with search tag,
' and outputs results to summary sheet named "Instructions".
' Note: The search tag is a local scope defined name range
' that contains the search data column address.

Dim Wks As Worksheet, wksTarget As Worksheet, rng As Range
Dim sOut$, sAddr1$, lCount&, n&, vData

Const sRngToSearch$ = "MyTag" '//edit to suit

Set wksTarget = ThisWorkbook.Sheets("Instructions")
'Assume comma delimited ID list stored in named range
With wksTarget
.Activate: vData = Split(.Range("IdList").Text, ",")
End With
If VarType(vData) < vbArray Then Exit Sub

On Error GoTo Cleanup
ReDim vDataOut(UBound(vData))
For n = LBound(vData) To UBound(vData)
sOut = ""
For Each Wks In ThisWorkbook.Worksheets
If bNameExists(sRngToSearch, Wks) Then
sOut = sOut & "," & Wks.Name & "=": sAddr1 = ""
With Wks.Range(sRngToSearch)
Set rng = .Find(What:=vData(n), LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns)
If Not rng Is Nothing Then
sAddr1 = rng.Address
Do
lCount = lCount + 1: Set rng = .FindNext(rng)
Loop While Not rng Is Nothing And rng.Address <> sAddr1
End If 'Not rng Is Nothing
End With 'Wks.Range(sRngToSearch)
sOut = sOut & lCount: lCount = 0
End If 'bNameExists
Next 'Wks
vDataOut(n) = Split(vData(n) & "|" & Mid$(sOut, 2), "|")
Next 'n

'Output to worksheet
Xform_1DimArrayOfArraysTo2D vDataOut
With wksTarget.Cells(Rows.Count, "A").End(xlUp)(2)
.Resize(UBound(vDataOut), UBound(vDataOut, 2)) = vDataOut
.EntireColumn.NumberFormat = "@"
End With


Cleanup:
Set wksTarget = Nothing: Set rng = Nothing
End Sub

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
G

GS

How/where does code find/get the IDs?

Here's 2 different approach examples that return the desired results.

FindSheetsWithID_A
Uses IDs stored in a cell named "IdList" on the results sheet.

FindSheetsWithID_B
Uses IDs stored as a list in colA on the results sheet.

Output is returned to A:B, where B contains a delimited string of all
sheet indexes where each ID is found. For each ID not found, B contains
"Not found".

Both examples use a search range (local scope) named "MyTag" to
accommodate the search range not being the same column on all search
sheets.

Code...

Option Explicit

Sub FindSheetsWithID_A()
' Looks for specified IDs on all sheets except results sheet,
' and builds a delimited output string of all sheet indexes where
found.
' Specified IDs to search for are stored as a comma delimited list
' on the results sheet in a cell (local scope) named "IdList".

Dim Wks As Worksheet, wksTarget As Worksheet, rng As Range
Dim sOut$, n&, vData

' The range to search is a local scope defined name range.
Const sRngToSearch$ = "MyTag" '//edit to suit

Set wksTarget = ThisWorkbook.Sheets("Instructions") '//results sheet
'Assume comma delimited ID list stored in named range
With wksTarget
.Activate: vData = Split(.Range("IdList").Text, ",")
End With
If VarType(vData) < vbArray Then Exit Sub

On Error GoTo Cleanup
ReDim vDataOut(UBound(vData))
For n = LBound(vData) To UBound(vData)
sOut = ""
For Each Wks In ThisWorkbook.Worksheets
If Not Wks Is wksTarget And bNameExists(sRngToSearch, Wks) Then
With Wks.Range(sRngToSearch)
Set rng = .Find(What:=vData(n), LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns)
If Not rng Is Nothing Then sOut = sOut & "," & Wks.Index
End With 'Wks.Range(sRngToSearch)
End If 'Not wksTarget And bNameExists
Next 'Wks
If sOut = "" Then sOut = vData(n) & "|Not found" Else _
sOut = vData(n) & "|" & Replace(Mid$(sOut, 2), ",", ", ")
vDataOut(n) = Split(sOut, "|")
Next 'n

'Output to worksheet
Xform_1DimArrayOfArraysTo2D vDataOut
With wksTarget.Cells(Rows.Count, "A").End(xlUp)(2)
.Resize(UBound(vDataOut), UBound(vDataOut, 2)) = vDataOut
.EntireColumn.NumberFormat = "@"
End With


Cleanup:
Set wksTarget = Nothing: Set rng = Nothing
End Sub 'FindSheetsWithID_A

Sub FindSheetsWithID_B()
' Looks for specified IDs on all sheets except results sheet,
' and lists all sheet indexes where each ID is found as a
' delimited output string. Specified IDs to search for are
' stored as a list in colA on the results sheet.

Dim Wks As Worksheet, wksTarget As Worksheet, rng As Range
Dim sOut$, n&, lStartNdx&, vData

Set wksTarget = ThisWorkbook.Sheets("Instructions") '//results sheet
'Assume comma delimited ID list stored in named range
With wksTarget
.Activate
vData = .Range("A1", .Cells(Rows.Count,
"A").End(xlUp)).Resize(ColumnSize:=2)
End With
If VarType(vData) < vbArray Then Exit Sub

'The range to search is a local scope defined name range.
Const sRngToSearch$ = "MyTag" '//edit to suit

'Accomodates if a header is included in vData
lStartNdx = IIf(vData(1, 1) = "Search IDs", 2, 1)

On Error GoTo Cleanup
For n = lStartNdx To UBound(vData)
sOut = ""
For Each Wks In ThisWorkbook.Worksheets
If Not Wks Is wksTarget And bNameExists(sRngToSearch, Wks) Then
With Wks.Range(sRngToSearch)
Set rng = .Find(What:=vData(n, 1), LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns)
If Not rng Is Nothing Then sOut = sOut & "," & Wks.Index
End With 'Wks.Range(sRngToSearch)
End If 'Not wksTarget And bNameExists
Next 'Wks
vData(n, 2) = IIf(sOut = "", "Not found", Replace(Mid$(sOut, 2),
",", ", "))
' vData(n, 2) = sOut
Next 'n

'Output to worksheet
wksTarget.Range("IdList").Resize(ColumnSize:=UBound(vData, 2)) =
vData

Cleanup:
Set wksTarget = Nothing: Set rng = Nothing
End Sub 'FindSheetsWithID_B

Function bNameExists(sName$, oSource) As Boolean
' Checks if sName exists in oSource
' Arguments:
' sName The defined name to check for
' oSource A ref to the Wkb or Wks being checked
' Returns:
' True if name exists

Dim x As Object
On Error Resume Next
Set x = oSource.Names(sName): bNameExists = (Err = 0)
End Function

Sub Xform_1DimArrayOfArraysTo2D(Arr())
' Restructures a 1D 0-based dynamic array of arrays to a fixed 2D
1-based array
' Arguments:
' Arr() The array of arrays to be converted
'
Dim v1, vTmp(), lMaxCols&, lMaxRows&, n&, k&

If VarType(Arr) < vbArray Then Exit Sub

lMaxRows = UBound(Arr) + 1: vTmp = Arr: Erase Arr
'Get size of Dim2
For n = LBound(vTmp) To UBound(vTmp)
k = UBound(vTmp(n))
lMaxCols = IIf(k + 1 > lMaxCols, k + 1, lMaxCols)
Next 'n

ReDim Arr(1 To lMaxRows, 1 To lMaxCols)
For n = LBound(vTmp) To UBound(vTmp)
For k = LBound(vTmp(n)) To UBound(vTmp(n))
Arr(n + 1, k + 1) = vTmp(n)(k)
Next 'k
Next 'n
End Sub

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top