Loading Userform with Recordet Information Of Selected Item (How to make faster) - sql

Im having a very minor issue, but is an issue nonetheless and its driving me nuts!
I have a Userform (VBA, using Excel as the Front End and Access as the Back End) which hast textboxes and a listbox.
What it does is fill the textboxes with information from an Access Database based on the selection the user makes on the listbox.
So if the user selects the entry with the "001" code, it goes to the Access DB, fecthes that record and populates the UserForm.
Below is the code:
Private Sub LtaInversiones_Click()
Dim rcon As Recordset
Dim sql As String
sql = "SELECT * FROM INVERSIONES WHERE CODIGO = "_
& LtaInversiones.List(LtaInversiones.ListIndex, 0)
Set rcon = BD.OpenRecordset(sql)
With rcon
CmbCodigo.Text = !Codigo
CmbTipo.Text = !TIPO
TxtTitulo.Text = !TITULO
TxtMonto.Text = !Monto
DTFCompra.Value = !FECHACOMPRA
DTFVencimiento.Value = !FECHAVENCIMIENTO
CmbPeriodicidad.Text = !periodicidad
TxtTCupon.Text = !TASACUPON
TxtPrecio.Text = !Precio
TxtRendimiento.Text = !rendimiento
TxtGPRedencion.Text = !GANANCIAPERDIDAREDENCION
TxtIAcum.Text = !INTERESESACUMULADOS
CmbEmisor.Text = !eMISOR
CmbOperador.Text = !OPERADOR
TxtNotas.Text = !NOTAS
If !FECHAREDENCION <> "" Then
DTFRedencion.Value = !FECHAREDENCION
ChkCInversion.Value = True
Else
ChkCInversion.Value = False
End If
.Close
End With
Set rcon = Nothing
CmdEliminar.Visible = True
CmdGuardar.Caption = "Modificar"
CmbCodigo.Enabled = True
The thing is, its working, but it slows down a bit. Ive tested the possible reasons, and it is definitely the fact that the query has to go look at what the list index is before going to the DB.
So I would like to ask you more experienced programmers (Im a lawyer by trade :/ ) If there is a better way of doing this.
The only thing that has ocurred to me is maybe loading all the records on initialization and then somehow accessing that data, as that would prevent the trip to the DB but am unsure whether that would improve performance or how to do it for that matter.
Thanks

What's stopping you from changing this:
LtaInversiones.List(LtaInversiones.ListIndex, 0)
to this?
LtaInversiones.Value
This will avoid a double lookup (List & ListIndex)
I personally avoid the "!" notation, preferring the fuller .Fields("ABC").Value
I'm not sure of any performance penalty or advantage there.

Related

What is causing the delay between recordset.update and the form/report getting the information?

Short version
I'm entering information in a database and fetching it shortly after, but for some reason, when I enter the information, it isn't immediately entered, so that when I try to fetch it, I get old results. Why does this happen? I thought the operations were synchronous.
Long version
I have a split Access database. At the moment the backend is on my own hard drive to speed up testing, eventually this backend will land on a server. Back when it was a combined frontend/backend database and before I had done a major code refactor (tbh, it was quite the clusterfornication before that), and now this is happening in a number of different scenarios, but pretty much every time I enter information and try to fetch it right after that. Why this happens is a mystery to me, since everything I was reading told me there is no multi-threading in VBA and that everything is synchronous if not specified otherwise, and I haven't enabled any asynchronous options.
Two Examples:
I add a record to the database then refresh the form that contains those new records. I'm not going to post the full code (unless it is deemed necessary), since I've modularized the code a lot. But essentially it boils down to this: the user clicks a button which executes this:
Private Sub Anhang_hinzufügen_Click()
If IsNull(Me.Parent.ID) Then
MsgBox "Bitte erst Felder ausfüllen, und anschließend Anhänge hinzufügen", vbInformation
Else
AnhängeAuswählen Me.Parent.Name, Me.Parent.ID
Me.Form.Requery
End If
End Sub
As part of the AnhängeAuswählen method, the method AddRecord is called:
Function AddRecord(TableName As String, fields() As String, values) As Long
Dim Table As DAO.Recordset
Set Table = LUKSVDB.OpenRecordset(TableName)
Table.AddNew
For i = LBound(fields) To UBound(fields)
If TypeName(Table.fields(fields(i)).Value) = "Recordset2" Then
Dim rs2 As DAO.Recordset2
Set rs2 = Table.fields(fields(i)).Value
If IsArray(values(i)) Then
For j = LBound(values(i)) To UBound(values(i))
rs2.AddNew
rs2!Value = values(i)(j)
rs2.Update
Next j
Else
rs2.AddNew
rs2!Value = values(i)
rs2.Update
End If
Else
Table.fields(fields(i)) = values(i)
End If
Next i
AddRecord = Table!ID
Table.Update
Table.Close
End Function
The record is created, that's not the problem. But when it executes Me.Form.Requery, the new record doesn't appear in the form. Only when I execute Me.Form.Requery a fraction of a second later does the record appear.
I add a record to the database using a form, update some information in the recordset with VBA, then requery the subreport with the records. The record appears immediately, but the details I added programmatically only appear when I execute Me.Parent.Requery a couple of seconds later.
The first form is a data entry form, so that as soon as the data is saved, it's blank in order to create a new record. The previous should then appear in the form. The button to create the new record looks like this:
Private Sub Anmerkung_Hinzufügen_Click()
currentID = Me.ID
mSaved = True
If Me.Dirty Then Me.Dirty = False
UpdateRecord "Anmerkungen", currentID, StringArray("Person", "Datum"), Array(User, Now)
Me.Parent.Requery
End Sub
The UpdateRecord is similar to the AddRecord method:
Function UpdateRecord(TableName As String, ByVal ID As Integer, fields() As String, values)
Dim Table As DAO.Recordset
Set Table = SeekPK(TableName, ID, True)
Table.Edit
For i = LBound(fields) To UBound(fields)
If TypeName(Table.fields(fields(i)).Value) = "Recordset2" Then
Dim subtable As DAO.Recordset2
Set subtable = Table.fields(fields(i)).Value
If IsArray(values(i)) Then
On Error Resume Next
Dim t
t = LBound(values(i))
If Developer Then On Error GoTo -1 Else On Error GoTo Fehler
If Err.Number = 0 Then
For j = LBound(values(i)) To UBound(values(i))
subtable.AddNew
subtable!Value = values(i)(j)
subtable.Update
Next j
End If
Else
subtable.AddNew
subtable!Value = values(i)
subtable.Update
End If
Else
Table.fields(fields(i)) = values(i)
End If
Next i
Table.Update
Table.Close
End Function
Does anyone know why this happens, and how I can prevent it? I could do a bit of a workaround with timers on the forms, so that it refreshes the form a couple of seconds later, but that seems like a kludgy workaround to me, especially considering I don't know how long it specifically takes, and the times could change drastically once the backend is on the server.
Additional information, in case it's necessary:
In the code I've posted I've removed some additional code for error handling and performance logging, but it doesn't have any impact on what's happening otherwise.
When the database is opened, a global variable LUKSVDB As DAO.Database is initialized:
Function ConnectDatabase(Backend As Integer)
Select Case Backend
Case 0: DatenOrt = 'redacted, folder in which the production/beta database is located on the server
Case 1: DatenOrt = 'redacted, folder in which I have a personal testing database on the server
Case 2: DatenOrt = 'redacted, folder in which I have the testing database on my own computer
End Select
Set LUKSVDB = OpenDatabase(DatenOrt & "\LUKS-Verwaltung_be.accdb", False, False, ";pwd=PASSWORD")
End Function
For testing purposes, ConnectDatabase is launched with a value of 2. However, if it's a problem on my own SSD, where latency is just about 0, then I can only assume it will be a problem on the server as well, where the latency is definitely not 0.

VBA: clear data from an object(Array) (SAP Object in VBA)

I am an SAP developer with little knowledge of VBA.
I am creating an VBA to post data to SAP using a BAPI. The coding is working fine & I am able to post data into SAP. My problem is I have several rows in my excel, I have to loop the rows one by one & upload data in SAP, after each upload i need to clear the contents, I am unaware of what syntax needs to be used to clear the data of the object variable. Below is the code snippet..
Set objbapicontrol = CreateObject("SAP.Functions")
Set objbapi = objbapicontrol.Add("BAPI_PO_CREATE1")
Set poheader = objbapi.exports.Item("POHEADER")
Set poitems = objbapi.tables.Item("POITEM")
For Each row In [POHEAD].Rows '##PO Header
If row.Columns(row.ListObject.ListColumns("SAP_PO_NUM").Index).Value = "" Then
ponum = (row.Columns(row.ListObject.ListColumns("PONumber").Index).Value)
poheader.Value("COMP_CODE") = (row.Columns(row.ListObject.ListColumns("COCD").Index).Value)
i = "00001"
n = 1
'###Loop Detail
For Each rowd In [PODET].Rows '##PO Detail
If (rowd.Columns(rowd.ListObject.ListColumns("PONumber").Index).Value) = ponum Then
poitem = (rowd.Columns(rowd.ListObject.ListColumns("Itemnumber").Index).Value)
poitems.Rows.Add
poitemsx.Rows.Add
poitems.Value(n, "PO_ITEM") = i
poitems.Value(n, "MATERIAL") = Material
Next '##PO Detail
returnfunc = objbapi.call
ponumber = objbapi.imports("EXPPURCHASEORDER")
Set retmess = objbapi.tables.Item("RETURN")
Set poitems = Nothing
next
I am using the code "Set POITEMS = NOTHING" but again when I set the object, the previous data is not cleared & duplicate enteries are created in SAP
Thanks in Advance!!
Regards,
Anil Malhotra
try using Set poitems = objbapi.tables.Item("POITEM") under the For loop.
set poitems= NOTHING will destroy the object but sometimes do not clear data. I faced this issue and was solved by moving the object creating code to the loop.
Hope it helps :)

OTA - ALM 11.52 - Building Graphs through OTA

I am trying to create reports in the 'Analysis View' using OTA and HP ALM 11.52.
I've searched the OTA Reference Documentation and looked for samples online and I've found a few samples, but none seem to work.
There seem to be three methods utilised:
TDConnection.GraphBuilder.BuildGraph(GraphDefinition)
TDConnection.testFactory.BuildSummaryGraph("TS_STATUS", "TS_STATUS", "", 0, myFilter, False, False)
and a third method involving an AnalysisItemFactory object that I can't find anywhere in the OTA documentation.
I've tried the first two and they seem to run without triggering an error, however, no graph appears in ALM.
Is there a difference between these methods and which is the cleanest method?
Here are my attempts so far:
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Method 1: GraphBuilder
'Set GB = QCConnection.GraphBuilder
'Set G1 = GB.CreateGraphDefinition(2, 0)
'G1.Property(0) = "TS_NAME"
'G1.Property(1) = "TC_STATUS"
'Set tsf = QCConnection.TestSetFactory
'Set myFilter = tsf.Filter
'myFilter.Filter ("TC_STATUS") = "Not(N/A)"
'G1.Filter = "Filter: Status[Not N/A]"
'Set g = GB.BuildGraph(G1)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Method 2: BuildSummaryGraph
'Dim testF
'Dim graph1
'Dim Filter
'Set testF = QCConnection.testFactory
'Set myFilter = testF.Filter
'myFilter.Filter("TS_STATUS") = "Not(N/A)"
'Set graph1 = _
'testF.BuildSummaryGraph("TC_NAME", "TS_STATUS", "", 0, myFilter, False, False)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Method 3: AnalysisItemsFactory? I can't find any documentation on this object, yet I've seen it referenced in other code samples.
'Set aiFolderFact = QCConnection.AnalysisItemFolderFactory
'Set aiFact = QCConnection.AnalysisItemFactory ~~~ This line actually runs fine so I know it at least exists. But I am definitely not using the proper methods below.
'Set G1 = aiFact.AddItem("")
'G1.Field("AI_PARENT_ID") = 1001 'Public
'G1.Field("AI_TYPE") = "Graph"
'G1.Field("AI_SUB_TYPE") = "Progress Graph"
'G1.Field("AI_OWNER") = qcUserName.Value
'G1.Field("AI_MODULE") = "requirement"
'G1.Field("AI_NAME") = "test graph"
'G1.Post
As I mentioned previously, all of these scripts run error free, but I see no graph in the Analysis View. I've also noticed that there seem to be no "Name" or "Path" fields.
I've taken a look at the tables, and there seems to be 'Analysis_Item_Folder' and 'Analysis Items' tables so It's know it's possible to do this through the OTA client. Is there an AnalysisItemFactory and could someone please kindly provide a sample script of what I'm looking for?
I was able to generate a report with the help of this HP ALM forum entry.
As in the forum mentioned it is not an official documented feature of HP ALM. Therefore it can be that in the future it won't work without replacement. Please keep that in mind.
In case the forum entry may get deleted I copied the answer by a user called "delarosa62" here (date of copy 2015/9/8):
Hi MichaelMotes and the rest of the community members.
I developed a VBA code to generate dashboard standard reports automatically. I get the "successful exception" you have mentioned. However my report does not get generated in my hard disk.
I don't get any errors.
I have adapted your Visial Basic Code to VBA using OTA. I have the otareport 1.0 Type Library and otaxml type lib registered in the tools/reference option in the VBA module window.
I am pasting my code below hoping you guys can give me some insight on this. I am not getting any errors. Just the exception which includes a successful completion message.
Sub externalSTDReports()
Dim reqFact
Dim reqFilter
Dim reqList
Dim gTDConn As Object
Set gTDConn = CreateObject("TDApiOle80.TDConnection")
'QC Connection data
login_id = ActiveWorkbook.Sheets("CONFIG").Cells(9, 3).value
login_passwd = ActiveWorkbook.Sheets("CONFIG").Cells(10, 3).value
domain_name = ActiveWorkbook.Sheets("CONFIG").Cells(11, 3).value
project_name = ActiveWorkbook.Sheets("CONFIG").Cells(12, 3).value
server_name = ActiveWorkbook.Sheets("CONFIG").Cells(13, 3).value
gTDConn.InitConnectionEx server_name
gTDConn.login login_id, login_passwd
gTDConn.Connect domain_name, project_name
Set Rep = New OTAREPORTLib.Reporter
Call Rep.SetConnection(gTDConn, 0) ' This line doesn´t return errors. But I don´t know if it is correct
Set RepConf = Rep.ReportConfig
Rep.File = "C:\Users\cris\AppData\Local\Temp\TD_80\4c223b57\Reports\std.html"
Rep.Template = "C:\Users\cris\AppData\Local\Temp\TD_80\4c223b57\Reports\default.xsl"
'******************************************************** filter Reports
Set aiFact = gTDConn.AnalysisItemFolderFactory
Set reportFact = gTDConn.AnalysisItemFactory
Set aiFilter = aiFact.Filter
Set aiList = aiFilter.NewList
Set anf = reportFact.Filter
Dim FilterStr As String
For Each ai In anf.NewList
reportName = ai.Name
reportID = ai.id
If reportName = "tmp" Then
FilterStr = ai.Field("AI_FILTER_DATA")
RepConf.Filter = FilterStr
On Error Resume Next
'i is empty. Don´t know why
i = Rep.Generate(0, 0) MsgBox i & " --- " & Rep.File Debug.Print Rep.File '-------------------- Exit For
End If
Next
Set gTDConn = Nothing
Set aiFact = Nothing
Set reportFact = Nothing
Set aiFilter = Nothing
Set aiList = Nothing Set anf = Nothing
Set RepConfig = Nothing
Set Rep = Nothing
MsgBox "END "
End Sub 'Pls HELP!!
Graphs can be generated under analysis folder, its a bit of a process because you need a sound understanding of the database, XML and OTA API. There is no direct API available for building graphs, I have created the code samples below
https://github.com/sumeet-kushwah/ALM_OTA_Wrapper/blob/master/ALM_Wrapper/Analysis.cs
Check the following functions
CreateDefectAgeGraph
CreateExcelReport
CreateDefectSummaryGraph
CreateSummaryGraph
These functions are called from the tests available below
https://github.com/sumeet-kushwah/ALM_OTA_Wrapper/blob/master/ALM_Wrapper_Tests/ALM_Wrapper_Test.cs
Look for test function
Test_AnalysisAndDashboardScripts
If you have any questions regarding the process, please let me know.

Better way to update ComboBox dynamically?

I was wondering if anyone had a suggestion or tip to improve the following function of my code. Basically I'm making a Update/Modify Form which fills its fields from a table of a DataBase, everything so far works great until I arrive at the comboboxes.
I have three of them, role, status and gender. The problem is that when I loaded the current user's information like this:
Dim lstDatos As New ArrayList()
lstDatos = gestorUsuario.consultarUsuario(idUsuario)
txtNombre1.Text = lstDatos(0)
txtNombre2.Text = lstDatos(1)
txtApellido1.Text = lstDatos(2)
txtApellido2.Text = lstDatos(3)
cmbGenero.DisplayMember = lstDatos(4) 'HERE
txtCorreo.Text = lstDatos(5)
txtCedula.Text = lstDatos(6)
txtTelefono.Text = lstDatos(7)
cmbRol.Text = lstDatos(8) 'HERE
cmbEstado.Text = lstDatos(9) 'And Here
Only the user's current Rol, Estado and Gender could be selected, to workaround that I made the following:
Private Sub updateRol(sender As Object, e As EventArgs) Handles cmbRol.Click
actualizarComboBox()
End Sub
Which calls the actualizarFunction:
Private Sub actualizarComboBox()
cmbGenero.Items.Add("Masculino")
cmbGenero.Items.Add("Femenino")
cmbEstado.DataSource = gestorUsuario.consultarEstados
cmbEstado.DisplayMember = "nombre_estado"
cmbEstado.ValueMember = "id_estado"
cmbRol.DataSource = gestorRol.consultarRoles
cmbRol.DisplayMember = "nombre"
cmbRol.ValueMember = "id_rol"
End Sub
It kinda works to be honest but...the first time the comboBox is selected you can see a visible jump when it loads the other options, also when I click the combo it automatically loses the "placeholder" if you will, of the user's current information and goes right up to the first option.
So if I have:
*B
As my user's current cmbRol.Text and I click the ComboBox it flickers a bit and changes to:
*A
-B
-C
Where * represent the selected or highlighted option.
If anyone had any suggestions or tips I would be very grateful. Thanks a lot.
Replace
cmbGenero.DisplayMember = lstDatos(4) 'HERE
cmbRol.Text = lstDatos(8) 'HERE
cmbEstado.Text = lstDatos(9) 'And Here
for this:
cmbGenero.SelectedItem = lstDatos(4) 'SelectedItem is sufficient because cmbGenero is not binding to Data Base
cmbRol.SelectedValue = lstDatos(8) 'SelectedValue is required because cmbRol and cmbEstado is binding to Data Base
cmbEstado.SelectedValue = lstDatos(9)

The 'If' statement part is not being carried out

I'm currently working on a project for school and it includes a login and register system.
This is a function that I have made. The "taken" variable will be passed back to the main program.
Dim taken As Boolean
Dim temp As String
For counter = 1 To totalrecords
FileGet(1, player_info)
temp = player_info.username
If TextBox2.Text = temp Then
msgbox("this is a messagebox")
taken = True
End If
Next
This is the part of the code that checks if any usernames are in use. If so, taken = true and then a message is displayed.
Now, for some reason the if statement part is not being carried out. The message box does not show at all. I have tested this by using more than one same username and the second (same) username is still added to the file. I'm very confused.
Part I believe is not working -
If TextBox2.Text = temp Then
taken = True
End If
You should use String.Equals(String1, String) to compare TextBox text and the temp variable.
In your case it should be written as this.
If String.Equals(TextBox2.Text, temp) Then
taken = true
End if