Combining two spreadsheets into one question

  • Thread starter Thread starter Allen Clark
  • Start date Start date
A

Allen Clark

I am still working on this data conversion project. In Access, there exists
a table called phones with the fields ID, PID, Phone_NO, Phone_Type,
fromdate, todate, extension. In another table, I have the ID, fname, mname,
etc.. I will be exporting these tables into excel workbooks (as I have been
for all other processes). Each field becomes a column in the spreadsheet.
The problem I have is that there may be more or less than one phone number
for each ID. The ID field is the common field between the tables. I need
to populate fields of Phone1, Type1, Phone2, Type2, and Fax from the phone
table(spreadsheet) for each ID, noting that some ID's will have no
associated phone numbers. This is performing a many to one merge of the
data.

Hopefully there is enough information here for some of the greats out there
to direct me to what formulas or methods would be recommended to perform
this task.

Thanks in advance,
Allen
 
In absence of schema DDL and sample data (which is netiquette in the
RDBMS ngs <g>), I'll say you want a LEFT JOIN with the Phones table on
the right. You can test for users with no row in the Phones table by
testing for null in the Phone field of the results set.

This would get you the *data* you require. However, it would not be in
the 'many-to-one' format you asked for. I'm sure it is *possible* to
do with SQL. One approach that springs to mind is to create a temp
table by UNIONing two queries, each sorting on the Phone column and
selecting the first then the second row using a COUNT, then self
joining the temp table to disregard the columns with nulls.

However, while possible I wouldn't recommend a SQL solution. It's
easier to do in the front end i.e. looping through a recordset ordered
on the Phone field, keep a row count for the current ID and convert
(non null) rows to a columns. Hard to write some sample code though
without knowing any info about your worksheet.

....so I'll start from scratch, build a new database with tables
stripped down to the basics and invent some sample data. Try this in a
new blank workbook:

Option Explicit

Sub Test()

Dim Cat As Object
Dim Con As Object
Dim rs As Object
Dim strConJet As String
Dim strSql1 As String
Dim strSql2 As String
Dim strSql3 As String
Dim rsFab As Object
Dim lngCurrentID As Long
Dim lngCounter As Long
Dim oTarget As Excel.Range

' Amend the following constants to suit
Const PATH As String = "" & _
"C:\Temp\"
Const FILENAME_JET As String = "" & _
"New_Jet_DB.mdb"

' Don't amend this one though
Const CONN_STRING_JET As String = "" & _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=<PATH><FILENAME>"

' Build connection string
strConJet = CONN_STRING_JET
strConJet = Replace(strConJet, "<PATH>", PATH)
strConJet = Replace(strConJet, "<FILENAME>", FILENAME_JET)

' Build sql statements
strSql1 = ""
strSql1 = strSql1 & "CREATE TABLE CommsUsers ("
strSql1 = strSql1 & " ID INTEGER NOT NULL PRIMARY KEY,"
strSql1 = strSql1 & " lname VARCHAR(35) NOT NULL,"
strSql1 = strSql1 & " fname VARCHAR(35) NOT NULL,"
strSql1 = strSql1 & " mname VARCHAR(35) NOT NULL"
strSql1 = strSql1 & " DEFAULT '{{NA}}'"
strSql1 = strSql1 & ");"

strSql2 = ""
strSql2 = strSql2 & "CREATE TABLE Phones ("
strSql2 = strSql2 & " ID INTEGER NOT NULL"
strSql2 = strSql2 & " REFERENCES CommsUsers (ID),"
strSql2 = strSql2 & " Phone VARCHAR(15) NOT NULL"
strSql2 = strSql2 & ");"

strSql3 = ""
strSql3 = strSql3 & "SELECT cm.ID, cm.lname,"
strSql3 = strSql3 & " cm.fname, ph.Phone"
strSql3 = strSql3 & " FROM CommsUsers cm"
strSql3 = strSql3 & " LEFT JOIN Phones ph"
strSql3 = strSql3 & " ON cm.ID=ph.ID;"

' Create new Jet database
Set Cat = CreateObject("ADOX.Catalog")
Cat.CREATE strConJet

' 'inherit' the connection
Set Con = Cat.ActiveConnection
Set Cat = Nothing

With Con

' Create tables
.Execute strSql1
.Execute strSql2

' Create some sample data
.Execute "INSERT INTO CommsUsers (ID, lname, fname)" & _
" VALUES (1, 'Livehulas', 'A')"
.Execute "INSERT INTO CommsUsers (ID, lname, fname)" & _
" VALUES (2, 'Katewudes', 'B')"
.Execute "INSERT INTO CommsUsers (ID, lname, fname)" & _
" VALUES (3, 'Hevitoxic', 'C')"
.Execute "INSERT INTO CommsUsers (ID, lname, fname)" & _
" VALUES (4, 'Norarules', 'D')"
.Execute "INSERT INTO Phones (ID, Phone)" & _
" VALUES (1, '123')"
.Execute "INSERT INTO Phones (ID, Phone)" & _
" VALUES (1, '456')"
.Execute "INSERT INTO Phones (ID, Phone)" & _
" VALUES (2, '555')"
.Execute "INSERT INTO Phones (ID, Phone)" & _
" VALUES (2, '444')"
.Execute "INSERT INTO Phones (ID, Phone)" & _
" VALUES (4, '789')"
End With

' Fabricate a recordset
Set rsFab = CreateObject("ADODB.Recordset")
With rsFab
.CursorType = 2 ' adOpenDynamic
.CursorLocation = 3 ' adUseClient
.LockType = 4 ' adLockBatchOptimistic
With .fields
.Append "ID", 3 ' Integer
.Append "lname", 200, 35 ' VarChar(35)
.Append "fname", 200, 35
.Append "Phone1", 200, 15 ' VarChar(15)
.Append "Phone2", 200, 15
End With
.Open
End With

' Open the real recordset
Set rs = Con.Execute(strSql3)

With rs

' Populate fabricated recordset
Do While Not .EOF
rsFab.AddNew _
Array("ID", "lname", "fname"), _
Array(!ID, !lname, !fname)

If IsNull(!Phone) Then
.MoveNext
Else
rsFab!Phone1 = !Phone
lngCurrentID = !ID
.MoveNext
If Not .EOF Then
If lngCurrentID = !ID Then
rsFab!Phone2 = !Phone
.MoveNext
End If
End If
End If
Loop

' Clean up
.Close
End With

Con.Close

' Copy data to ThisWorkbook
With rsFab
.UpdateBatch
.MoveFirst
Set oTarget = ThisWorkbook.Worksheets(1) _
.Range("A1")
For lngCounter = 1 To .fields.Count
oTarget(1, lngCounter).Value = _
.fields(lngCounter - 1).Name
Next
End With

oTarget(2, 1).CopyFromRecordset rsFab

End Sub

--
 
Frank,

Maybe this will help explain what I am trying to accomplish.

Excerpt from t_address table. Additional fields that need to be populated
from t_phones are phone1, type1, phone2, type2, fax

Customer_no Address_no Street2(Apt, etc) Street1
4 15005 Emory Ln
5 1801 E Jefferson St Apt 603
7 15101 Emory Ln
8 4512 Traymore St
9 8316 Robey Ave
11 7211 Exeter Rd
12 796 Nelson St
13 3605 Lawrence Ave
15 1342 Alderton Ln
16 4617 Derussey Pkwy
18 10201 Grosvenor Pl Apt 1624
19 7774 Heatherton Ln
20 14700 Harvest Ln
21 1703 Mount Washington Ct Apt K
22 7451 Arlington Rd
24 8104 Clay Dr


The t_phones looks like this:

Pid Id Number Type
45 4 3014606920 Home
46 8 3015300541 Home
47 9 (703) 560-7795 Home
48 11 3016524019 Home
49 12 (301) 762-3267 Home
50 13 3019334163 Home
20772 13 3019337572 Day
52 18 (301) 897-9059 Home
53 19 3012996493 Home
54 20 3013842420 Home
55 21 4106645323 Home
56 22 3019331052 Home
57 24 3018394544 Home
58 26 (202) 667-8194 Home
59 28 3017628206 Home
61 30 3019330834 Home
64 35 (301) 582-3582 Home
3465 35 (301) 925-2300 Work
20693 37 (301) 299-8457 Day
66 38 3015640351 Home
67 39 (703) 644-1867 Home
3466 39 2023075270 Work


The data starts below the header row in both worksheets. I am trying to
match on Customer_no(column A) in t_address to Id (column B) in t_phones.
If a match is found, the corresponding phone number needs to go into
t_address in the Phone1 field, and the corresponding Type information goes
into Type1 column, then it needs to check to see if another phone number
exists for this same Customer_no(or Id). If another phone number exists, it
needs to go into Phone2, and the corresponding Type needs to go into Type2.
We then need to check to see if there is a fax number. If so, (type from
t_phones=fax), that number needs to go into the t_address table.

Thank you Frank for your previous assistance with other functions. I
understand, however, if you pass on this one. Hopefully you might be able
to point me in the right direction, though.

Thanks in advance,
Allen
 
Hi Allen
if I understood your example (and the column# correctly) try the
following in the phone1 column in your t_adress table (E2?)
=IF(ISNA(VLOOKUP(A2,'t_phones'!$B$2:$C$1000,2,0)),"",VLOOKUP(A2,'t_phon
es'!$B$2:$C$1000,2,0))
copy down

for the type1 (cell F2) use
=IF(ISNA(VLOOKUP(A2,'t_phones'!$B$2:$D$1000,3,0)),"",VLOOKUP(A2,'t_phon
es'!$B$2:$D$1000,3,0))
also copy down

phone2 (G2): Use the following array formula: Entered with
CTRL+SHIFT+ENTER:
=IF(ISERROR(INDEX('t_phones'!$C$2:$C$1000,SMALL(IF('t_phones'!$B$2:$B$1
000=A2,ROW('t_phones'!$B$2:$B$1000)),2)-1)),"",INDEX('t_phones'!$C$2:$C
$1000,SMALL(IF('t_phones'!$B$2:$B$1000=A2,ROW('t_phones'!$B$2:$B$1000))
,2)-1))
copy down

type2 (H2): Also an array formula
=IF(ISERROR(INDEX('t_phones'!$D$2:$D$1000,SMALL(IF('t_phones'!$B$2:$B$1
000=A2,ROW('t_phones'!$B$2:$B$1000)),2)-1)),"",INDEX('t_phones'!$D$2:$D
$1000,SMALL(IF('t_phones'!$B$2:$B$1000=A2,ROW('t_phones'!$B$2:$B$1000))
,2)-1))
copy down

Not sure about your fax number?
 
Some more clues to the schema, some schema info completely different
and sample data. After some slight adjustments, this again in a new
blank workbook to test (don't forget to edit the comments to point to
your database):

Option Explicit

Sub Test2()

Dim Cat As Object
Dim Con As Object
Dim rs As Object
Dim strConJet As String
Dim strSql3 As String
Dim rsFab As Object
Dim lngCurrentID As Long
Dim lngCounter As Long
Dim oTarget As Excel.Range

' Amend the following constants to suit
Const PATH As String = "" & _
"C:\Tempo\"
Const FILENAME_JET As String = "" & _
"New_Jet_DB.mdb"

Const CONN_STRING_JET As String = "" & _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=<PATH><FILENAME>"

' Build connection string
strConJet = CONN_STRING_JET
strConJet = Replace(strConJet, "<PATH>", PATH)
strConJet = Replace(strConJet, "<FILENAME>", FILENAME_JET)

strSql3 = ""
strSql3 = strSql3 & "SELECT ad.Customer_no, ad.Address_no,"
strSql3 = strSql3 & " ad.Street2, ad.Street1, ph.Number,"
strSql3 = strSql3 & " ph.Type FROM t_address ad"
strSql3 = strSql3 & " LEFT JOIN t_phones ph"
strSql3 = strSql3 & " ON ad.Customer_no = ph.ID;"

' Open connection
Set Con = CreateObject("ADODB.Connection")

With Con
.ConnectionString = strConJet
.Open
End With

' Fabricate a recordset
Set rsFab = CreateObject("ADODB.Recordset")
With rsFab
.CursorType = 2 ' adOpenDynamic
.CursorLocation = 3 ' adUseClient
.LockType = 4 ' adLockBatchOptimistic
With .fields
.Append "Customer_no", 3 ' Integer
.Append "Address_no", 200, 6 ' VarChar
.Append "Street2", 200, 35
.Append "Street1", 200, 15, 64 + 4
.Append "phone1", 200, 20, 64 + 4
.Append "type1", 200, 10, 64 + 4
.Append "phone2", 200, 20, 64 + 4
.Append "type2", 200, 10, 64 + 4
.Append "fax", 200, 20, 64 + 4
End With
.Open
End With

' Open recordset
Set rs = Con.Execute(strSql3)

With rs

' Populate fabricated recordset
Do While Not .EOF
rsFab.AddNew _
"Customer_no", _
!Customer_no

rsFab!Address_no = !Address_no
rsFab!Street2 = !Street2
rsFab!Street1 = !Street1

If IsNull(!Number) Then
.MoveNext
Else
rsFab!Phone1 = !Number
rsFab!Type1 = !Type
lngCurrentID = !Customer_no
.MoveNext
If Not .EOF Then
If lngCurrentID = !Customer_no Then
rsFab!Phone2 = !Number
rsFab!Type2 = !Type
.MoveNext
End If
End If
End If
Loop

' Clean up
.Close
End With

Con.Close

' Copy data to ThisWorkbook
With rsFab
.UpdateBatch
.MoveFirst
Set oTarget = ThisWorkbook.Worksheets(1) _
.Range("A1")
For lngCounter = 1 To .fields.Count
oTarget(1, lngCounter).Value = _
.fields(lngCounter - 1).Name
Next
End With

oTarget(2, 1).CopyFromRecordset rsFab

End Sub

--
 
Back
Top