I'm currently trying to figure out a way to connect to HP QC 12 via MS Access and import the data found in table bug via a simple query. However, I'm having a hard time getting the HP QC data into a usable query.
I've tried two ways so far:
Public Function import_HPQC()
Dim QCConnection
Dim Com
Dim HPQC_RST As TDAPIOLELib.Recordset
Set QCConnection = CreateObject("TDApiOle80.TDConnection")
QCConnection.InitConnectionEx <>
QCConnection.login <>, <>)
QCConnection.Connect <>, <>
QCConnection.IgnoreHTMLFormat = True
Com.CommandText = "SELECT * FROM bug"
Com.Execute
Set HPQC_RST = Com.Execute
rcount = 0
HPQC_RST.First
Do Until HPQC_RST.EOR
rcount = rcount + 1
HPQC_RST.Next
Loop
MsgBox (rcount)
QCConnection.Logout
End Function
This first way works in the way that I'm able to at least get an accurate record count of what is contained in bug but I can't get past this part. I can't figure out a way to simply run an insert into against HPQC_RST.
The other way I've tried is basically the same, but instead of a select query I'm attempting to define BugFactory.NewList("") as a recordset but that just isn't working either. I'm able to loop through a BugList in the following fashion but I think it's a really messy solution and I would much rather simply append everything from bug directly into an MS Access table.
Set BugFactory = QCConnection.BugFactory
Set BugList = BugFactory.NewList(“”)
For Each Bug In BugList
HPQC_Table.AddNew
HPQC_Table![ID] = Bug.Field("BG_BUG_ID")
HPQC_Table.Update
Next
Any help would be greatly appreciated as I've been working on this for a few days and have made very little progress.
You're connecting to the API, not to the actual database. If the API only provides recordset-like objects that you can loop over, that's probably what you will have to do.
(/me smiling a little at the remnants of TestDirector in the object names)
Related
I have an Access database and an Excel workbook.
What I need to do is query the database and paste the query into a worksheet.
The issue is Runtime. I have stepped throught the program and everything works, but it works extremely slow, we're talking up to 30 second run times per query, although most of this run time is coming with the CopyFromRecordset call.
The database has over 800k rows in the table I'm querying.
Currently at my company there are people every morning who manually query the tables and copy and paste them into excel. I'm trying to remove this process.
Here is what I have:
Sub new1()
Dim objAdoCon As Object
Dim objRcdSet As Object
' gets query information '
Dim DataArr()
Sheets("Data2").Activate
DataArr = Range("A1:B40")
For i = 1 To UBound(DataArr)
job = DataArr(i, 1)
dest = DataArr(i, 2)
If InStr(dest, "HT") > 0 Then
OpCode = "3863"
ElseIf InStr(dest, "HIP") > 0 Then
OpCode = "35DM"
End If
strQry = "SELECT * from [BATCHNO] WHERE ([BATCHNO].[Job]='" & job & "') AND ([BATCHNO].[OperationCode] = " & "'" & OpCode & "')"
Set objAdoCon = CreateObject("ADODB.Connection")
Set objRcdSet = CreateObject("ADODB.Recordset")
objAdoCon.Open "Provider = Microsoft.Jet.oledb.4.0;Data Source = C:\Users\v-adamsje\Desktop\HTmaster.mdb"
'long run time
objRcdSet.Open strQry, objAdoCon
'very long run time
ThisWorkbook.Worksheets(dest).Range("A2").CopyFromRecordset objRcdSet
Set objAdoCon = Nothing
Set objRcdSet = Nothing
Next i
End Sub
Any help is appreciated. I am new to VBA and Access so this could be an easy fix. Thanks
Excel is very good at getting data for itself, without using VBA.
On the DATA ribbon
create a connection to a table or view of data somewhere (eg mdb or SServer)
then use the "existing connections" button to add data from your connected table to a worksheet table (ListObject).
You can even set the workbook (ie connection) to refresh the data every 12 hours.
Repeat for all the tables /view you need to grab data for. You can even specify SQL as part of the connection.
Let excel look after itself.
I just grabbed a 250,000 row table from a "nearby" disk in 2 secs.
It will look after itself and has no code to maintain!
I don't see how the CopyFromRecordset can be improved. You could copy the recods programmatically (in VB) record-by-record but that will probably be slower than the CopyFromRecordset.
You can move the CreateObject statements out of the loop, With the connection and RecordSet already created, this could be faster:
Set objAdoCon = CreateObject("ADODB.Connection")
Set objRcdSet = CreateObject("ADODB.Recordset")
For i = 1 To UBound(DataArr)
...
next i
Set objRcdSet = Nothing
Set objAdoCon = Nothing
You could also try ADO instead of DAO. ADO seems to perform faster on large record sets.
But also the server could be an issue, for example, are there indexes on Job and OperationCode? If not, then the slowness could be the server selecting the records rather than Excel placing them in the worksheet.
Whelp, never found out why the CopyFromRecordset runtime was obsurd, but solved my problem by pulling the whole table into excel then into an array, looping through that and putting them in respective sheets. From 30min runtime to <1min
I am currently making an search loop in VBA for my database. In this database I Have 2 Tables, one with the customers records called Main and another one with search words called Sparr. The idea is to use a filter to filter out the customers that match any of the search words in the Sparr table. Any customer that does not match any of the search words gets added to another table called filteredCustomerT.
For example:
table "Main"
Field "Mail"
mike#coolmail.com
john#hotmail.com
dave#mail.com
jonny#mailx.com
table "Sparr"
Field "sparrord"
hotmail
jonny
table "Testtable"
Field "testMail"
mike#coolmail.com
dave#mail.com
So if I run this VBA code I want john#hotmail.com and jonny#mailx.com to be filtered out. The Main table contains 200k records and the Sparr table contains 2k search words. I have wrote some VBA code that should loop through the Main table. For every record in the Main table a have another nested loop that loops through the Sparr table so see if there is any match. If there is not a match the VBA code copies the entry to anther table called Testtable. I Use the inStr function to do the matching.
Below I have posted the VBA code that does not seem to work. Can anyone help me ant maybe point out a fault in the code. I am very new to VBA programming.
Option Compare Database
Option Explicit
Sub filter()
Dim mainMail As Recordset
Dim sparrSokord As Recordset
Dim testtableTestmail As Recordset
Dim mainTemp As String
Dim sparrTemp As String
Dim match As Integer
Set mainMail = CurrentDb.OpenRecordset("Main")
Set sparrSokord = CurrentDb.OpenRecordset("Sparr")
Set testtableTestmail = CurrentDb.OpenRecordset("Testtable")
Do Until mainMail.EOF
mainTemp = mainMail![Mail]
match = 0
sparrSokord.MoveFirst
Do Until sparrSokord.EOF
sparrTemp = sparrSokord![sparrord]
If (InStr(mainTemp, sparrTemp) <> 0) Then
match = 1
Exit Do
End If
sparrSokord.MoveNext
Loop
If (match = 0) Then
testtableTestmail.AddNew
testtableTestmail![testMail] = mainTemp
testtableTestmail.Update
End If
mainMail.MoveNext
Loop
End Sub
InStr can operate in unexpected ways is you have nulls/empty strings/etc, involved.
I've noticed that you have nothing resetting the position of SearchwordWord back to the beginning of the record set once you reach the end.
Naturally you would do something like SearchwordWord.MoveFirst before the Do Until SearchwordWord.EOF. It doesn't hurt to do one before the Do Until customerMail.EOF either
I'll also note the Do Until always executes the contents of the loop, and then checks the condition at the end (which could be giving you unexpected results, especially with SearchwordWord being at EOF after the first successful pass of the loop.
You probably want to use a while/wend instead for both do untils (I practically never use them as it is). This is probably the biggest cause of your grief.
The problem is now solved. I just had to close some programs and try again with the updated code above. Worked just fine!
Okay, friends, I'm leaving my job in a week and a half, and I'm trying to make what I've done easier for my boss to do. He has no access knowledge, so I'm trying to create a form that will automate the reports I've been generating. Rather than create a different form for all the different reports, I'm trying to automate it from a table of parameters. Here's what I'm going for:
I have a table, which I have created, which is comprised of 5 fields. I'd like to use these fields to fill parameter fields in a standard form template. The five fields in my table are as follows:
The type of query being run (the result spit out)
The queries that generate this report, separated by a comma and no space. "QRYNAMEA,QRYNAMEB"
The Table which these queries generate, which will be used by transferspreadsheet
The destination excel file, which already has a pivot table set up to feed of the data.
The input sheet of this excel file. Currently, all of these sheets are called "Input". (that isn't important)
My issue comes with having no idea where to go after I've made my combo box. I know enough visual basic to automate my queries, but not enough to populate the form with the information in 3,4 and 5 (so far, I've been manually changing these for different queries). I have no idea how to look up the record in the table from the choice in the 'choosebox', and then select individual fields from that in my automation.
I'm pretty confident in my ability to parse #2 and automate the queries, and to put the values into the fields I'm looking at, but I don't know how to actually pull those values from the table, before I can do these things. I also can't seem to describe this well enough for google to help me.
Has anyone done something like this before? I'm assuming I just lack knowledge of one of the VBA libraries, but I've not had any luck finding out which.
edit:
my inclination at this point is to create a query for this table, which will return a single field depending on the input I give. I can imagine doing this in SQL, but I still don't know how to populate the forms, nor extract the field object from the table once I get it.
I have to head out for the day, but I'll be back on Friday to keep working on this, and I'll post my solution, once I find it. This seems like a unique conundrum, and it would be nice to give an answer to it.
Final edit: code is polished (does not have much in the way of error handling):
The first method, which pulls the fields from the table and populates the form, is activated by choosing a new entry in the combo box and looks like this:
Private Sub QuerySelect_Change()
Dim db As Database
Dim rec As Recordset
Set db = CurrentDb
Set rec = db.OpenRecordset("SELECT [Queries to Run], [Source Table], [Destination Spreadsheet], [Destination Sheet Name] FROM TBL_QRY_SETTINGS WHERE TBL_QRY_SETTINGS.[Query Type] Like '" & [Forms]![QuerySelector]![QuerySelect] & "';")
[Forms]![QuerySelector]![QueriesToRun].Value = rec("Queries to Run")
[Forms]![QuerySelector]![SourceTable].Value = rec("Source Table")
[Forms]![QuerySelector]![FileDest].Value = rec("Destination Spreadsheet")
[Forms]![QuerySelector]![SheetName].Value = rec("Destination Sheet Name")
Set rec = Nothing
Set db = Nothing
End Sub
The second code pulls that data to run the query. I like how this turned out. It runs when a button near the combobox is clicked.
Private Sub DynamicQuery_Click()
Dim qryArray As Variant
Dim i As Integer
qryArray = Split([Forms]![QuerySelector]![QueriesToRun], ",")
DoCmd.SetWarnings False
For i = LBound(qryArray) To UBound(qryArray)
Debug.Print qryArray(i)
DoCmd.OpenQuery (qryArray(i))
Next
DoCmd.SetWarnings True
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, [Forms]![QuerySelector]![SourceTable], _
[Forms]![QuerySelector]![FileDest], _
True, [Forms]![QuerySelector]![SheetName]
End Sub
Note that the final code for part (1) is almost the same as the selected answer, except that I am grabbing more than one field. This works because I know that I have unique "Query Types", and my recordset will only contain one record.
Anyway, I hope some people stumble upon this and find it useful. Send me a message if you do. As far as I can tell from brief googling, this sort of automation work has not been done in access. It should make it easier for access-illiterate to run their own queries, and be simple for designers to add to, if they want all their queries available after a few clicks.
Someone could conceivably use this to automate a variety of reports in sequence, by iterating through a table like the one I reference.
I may be massively misunderstanding what you're doing, but I think it's as easy as creating a new form using the form wizard. It will let you choose the table that contains the data, and it will let you choose which fields you want to add.
You can later change any of the textboxes to combo boxes which will allow you to limit the choices available to fill in.
Am I understanding that correctly?
EDIT: This will fill a variable (MyRandomField) with the contents of a field in a table
Dim db as Database
Dim rec as Recordset
set db = CurrentDB
set rec = db.OpenRecordSet("Select SomeField from SomeTable Where Something = 'SomethingElse'")
MyRandomField = rec("SomeFieldName")
set rec = Nothing
set db = Nothing
I design (PHP) db editors in the gaming world as a past time. I took up the challenge of doing the same thing, but this time with VB (originally 6, but MySQL is tricky) so I'm working with 2008.
One of the tables has a massive amount of info and I only need to display 4 or 5 fields from it as a search result (there are over 100+ fields)
I know how to populate the grid with the whole table, but do not know how to do it via specific fields without going into a very long way around it.
This is my first time from VB6 to VB.NET - sadly not too impressed (looks like they (M$) have deviated from "BASIC" and went for the C++ engine format - super ugly (but I digress).
Try
conn.Open()
da = New MySqlDataAdapter(sqlQRY, conn)
Dim cb As MySqlCommandBuilder = New MySqlCommandBuilder(da)
da.Fill(ds, "big_table")
DataGridView1.DataSource = ds
DataGridView1.DataMember = "big_table"
Catch ex As Common.DbException
MsgBox(ex.ToString)
Finally
conn.Close()
End Try
The above works fine, but I do not not need all 100+ fields displaying. Just want player name, level, if they are online and a few other fields to show - from here I can select a row and process the data elsewhere in the program.
Hope that made sense :-)
edit:
clarification: I need to know how, at run time, to create the datagrid to accept the results of my query so it does NOT display the whole record.
Is it possible you specify all fields in your query with a *? Just declare sqlQRY like:
SELECT Player_Name, Level, Online_Status, A_Few_Other_Fields FROM Players;
i am new to ms-access, and i have started to look at code that works. unfortunately it is completely uncommented.
Private Sub OKbut_Click()
Dim dt As Date
dt = Now()
Set rstOrder = New ADODB.Recordset
rstOrder.Open "tblUsers", CurrentProject.Connection, adOpenStatic, adLockOptimistic
If rstOrder.Supports(adAddNew) Then
With rstOrder
.AddNew
.Fields("title") = title
.Fields("first") = first
.Fields("last") = last
.Fields("gender") = gender
.Fields("date_submitted") = dt
.Update
End With
End If
rstOrder.Close
Set rstOrder = Nothing
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT id FROM tblUsers WHERE date_submitted=#" & dt & "#")
duser = rs.Fields("id")
rs.Close
Set rs = Nothing
Do While Not user_defined(duser)
DoCmd.OpenForm "define_user_frm", , , , , acDialog
Loop
'Forms(0).user_lst.RowSource = "select * from users where id=" & duser
Me.SetFocus
DoCmd.Close
End Sub
what does the function Now() do?
ADODB.Recordset is just a way to connect to a table?
adOpenStatic, adLockOptimistic what are these?
why are we checking this: if rstOrder.Supports(adAddNew) ?
why do we need to do this: Set rstOrder = Nothing?
what does this do:? Do While Not user_defined(duser)
DoCmd.OpenForm "define_user_frm", , , , , acDialog
Loop
Approaching existing code like this isn't the best way to learn to program. There are plenty of online tutorials that will help you get started and progress in a linear manner. The other advice I'd give is to try things out for yourself. Write a small method that contains "MsgBox Now()" and run it to see what happens. Then run it a couple of seconds later.
I can't over-recommend finding a beginners tutorial.
However that said . . .
Now - returns the computers system date and time, at the moment it's called
Yes - Among other things.
Hints to the query engine. Open Static says you don't want to see rows added after the record set is retrieved, optimistic locking tells the engine which record locking option to use (the other is pessemistic)
Checking this because you can't add records to all resordsets (e.g. complex queries joining several tables)
Not stricly necessary, but better for memory management, otherwise the recordset object (and all associated resources - memory, handles etc) wouldn't be disposed until the end of the method.
Opens an ms access form until the condition "user_defined(duser)" returns true
Hope this helps.
what does the function Now() do?
Now() returns the current system date and time
ADODB.Recordset is just a way to connect to a table?
Yes - more importantly, it is a good way to iterate through records of a dataset individually. Like a cursor in SQL Server. You could do something like
While not rstOrder.EOF
'a.k.a. while there are still records left to iterate through
'Do something
End While
adOpenStatic, adLockOptimistic what are these?
From http://www.dotnetspider.com/forum/16958-In-VB-What-difference-between-adopendynamic.aspx
adOpenForwardOnly - this is the default cursor if no other is specified. This cursor allows only forward movement through a recordset
adOpenKeyset - this cursor supports forwards as well as backwards navigation. It also allows you to update a recordset and all changes will be reflected in other users recordsets. The cursor also supports bookmarking
adOpenDynamic - this cursor supports forward and backward navigation but bookmarks may not be supported (ie Access). Any changes made to data are immediately visible with no need to resynchronise the cursor with the database
adOpenStatic - this cursor uses a static copy of data from the database and therefore no changes to the data are visible and supports forward and backward navigation
why are we checking this: if rstOrder.Supports(adAddNew) ?
It's a way of writing more robust code - i.e. before attempting to add a new record, first check whether the recordset supports the addition of new records.
why do we need to do this: Set rstOrder = Nothing?
Frees the recordset from memory. Not absolutely necessary but again, makes for more robust code.
what does this do:? Do While Not user_defined(duser) DoCmd.OpenForm "define_user_frm", , , , , acDialog Loop
Checks for existence of a user and if it doesn't exist, it opens a form called "define_user_frm" which I assume allows for creating a new user.
what does the function Now() do?
Place the cursor on the word Now in your subroutine, then press the F1 key. Is Access' help not helpful for answering your question?
I'm trying to suggest it should be quicker for you to use the built-in Help feature for a question like that, instead of posting to Stack Overflow and waiting for responses. Then you only need post the questions that Help doesn't answer adequately for you.
I'm very rusty with VB/Access but:
1) Now returns the current date and time
2) Recordset is a set of records - from memory doesn't have to be a table, could be a query.
3) Those are flags to indicate how the table (as it is a table in this case) should be accessed can't remember static but the Lock says that we're going to use optimistic locking i.e. we will basically assume that the record won't be changed by anyone else.
4) Because you can open recordsets in a number of different ways - so it may well be the case that you have a read-only set of data. In the context of the example its notionally redundant but in terms of good practice its a reasonable bit of defensive programming.
5) Probably don't but again its sensible defensive programming and it ensures that all resources associated with the recordset are released. rstOrder is coming from somewhere external to the sub so not leaving it in an open state is sensible.
6) The loop repeats until the function user_defined(duser) returns true. duser being the - erk, that looks horrid - ID returned by the query but that doesn't look safe. DoCmd.Open form is popping up the "define_user_form" as a dialog so... if the user doesn't exist then fire up the dialog to define the user then check again that the user has been defined. That's also a bit questionable (although of course without a bit more context its hard to tell).
Basically VBA in Access is mostly VB6 but with sufficient differences to drive one slightly mad... there's a whole pile of stuff that you can assume to exist in access that you have to be rather more explicit about in VB.OLD
what does the function Now() do?
Returns a Variant (Date) specifying the current date and time according your computer's system date and time.
ADODB.Recordset is just a way to connect to a table?
The ADO Recordset object is used to hold a set of records from a database table. A Recordset object consist of records and columns (fields). It can be used to open tables, queries, custom SQL statements, etc.
adOpenStatic, adLockOptimistic what are these?
adOpenStatic: Provides a static copy of the records (you can't see additions, changes or deletions by other users), but all types of movement are enabled (e.g. .moveNext, .MoveFirst, .moveLast, etc).
adLockOptimistic: Record locking is performed only when you call the Update method.
why are we checking this: if rstOrder.Supports(adAddNew) ?
Checking whether the recordset allows new records to be added.
why do we need to do this: Set rstOrder = Nothing?
When you're completely finished with rstOrder, setting it equal to Nothing removes it from memory. You can think of it as a simple version of garbage collection.
what does this do:? Do While Not user_defined(duser) DoCmd.OpenForm
"define_user_frm", , , , , acDialog
Loop
Assuming user_defined() is a custom function, it loops through the record just added and opens a form that allows you to define the user.
Reference:
http://www.w3schools.com/ado/ado_ref_recordset.asp
what does the function Now() do? - Creates a DateTime for the current date and time the function is being run.
ADODB.Recordset is just a way to connect to a table? This is an object or saying that rstOrder is not a ABDODM.Recordset with a method to open the connection to the DB.
why do we need to do this: Set rstOrder = Nothing? - This is cleaning up the connection so that the computer does not keep the memory and for rstOrder. Other wise after running your computer might slow down or have less memory.
what does this do:? Do While Not user_defined(duser) DoCmd.OpenForm "define_user_frm", , , , , acDialog Loop - This is a loop that will be repeated and will Open an Access form as long as user_defined is not duser.
Now() just returns the current date and time
ADODB.Recordset is in this instance being used as a way to connect to a table. It is generally used to connect to an external (read SQL) dataset. And can be populated from a query or stored procedure. Similar to the access builtin Recordset
These are switches used to set certain options in the connection. I would recommend reading over the MSDN documentation.
Not every recordset supports adding records (such as that returned from a query) this simply checks that before you attempt to add a record. It is part of writing code that won't throw errors.
This is simply a way to clean up the memory. As far as I know VBA is garbage collected but if you have a large recordset this can free up some memory sooner.
I'm not sure about this here. but it looks like it's calling a user defined function and it returns false it opens a form.