Querying in MS Access 2013 excluding special characters - ms-access-2013

I am trying to create an update query in MS Access where I will pull a few fields of information from one table if one of the fields matches and the rest are blank. For example:
**Table 1**
SKU Description Weight Lead Time
C210657 NULL NULL NULL
221AB0909 NULL NULL NULL
VA12345 NULL NULL NULL
221AB09 NULL NULL NULL
**Table 2**
SKU Description Weight Lead Time
F-210-223.2 Hammer 2.1 3.1
201-ABF-345 Car 12546.0 65.0
C_210657 Apple 0.2 1.0
34_AA_332 Puppy 5.5 55.0
221 AB 0909 Stereo 12.0 875.0
VA12345_123-A Labor 0.0 0.0
So I want the query to fill in columns 2 through 4 of table 1 with information from table 2. All four of the items in table 1 have a match in table 2, there are just special characters (-, _, ., ), that are in the way. How can I have the query ignore them? Thanks

Which way you go depends on what you're willing to do. If it's a big database, you might want to add a new field [SKU_Index] that is SKU with the special characters removed and link on that.
If that's not a possibility, then you can do a calculated subquery and link on the calculated field...but it can be a little slow.
You would need to write a procedure that removes the special characters from a passed string. Let me know if you would like help with that.
Then you do a query on Table 2 like this:
Select SKU2:RemoveSpecialChars([SKU]), Description, Weight, [Lead Time] From [Table 2];
RemoveSpecialChars() would be your procedure.
You save that query (let's call it PreQuery). Create a new query and bring in PreQuery and Table 1 linking SKU from Table 1 to SKU2 from PreQuery, and update the relevant fields.
Ideally, cause storage is cheap, I would keep a second field without the special characters and perhaps index on it.
Here's example code for how that would work:
Public Function RemoveSpclChars(strIn As String) As String
' Comments : removes any special characters
' Parameters: strIn - string to check
' Returns : resulting string with removed special characters, can be empty
'
Dim lngCounter, intChar As Integer
Dim chrTmp As String * 1
Dim strTmp As String
On Error GoTo PROC_ERR
strTmp = ""
' Walk through the string
For lngCounter = 1 To Len(strIn)
' Get the current character
chrTmp = Mid$(strIn, lngCounter)
intChar = Asc(chrTmp)
' Test if alpha or numeric only
If (intChar >= Asc("a") And intChar <= Asc("z")) Or (intChar >= Asc("0") And intChar <= Asc("9")) Then
strTmp = strTmp & chrTmp
End If
Next lngCounter
PROC_EXIT:
RemoveSpclChars = strTmp
Exit Function
PROC_ERR:
Dim strErr As String
strTmp = "ERROR: " & Trim(Str(Err.Number)) & ":" & Err.Description
Resume PROC_EXIT
End Function

Related

Append x amount of records in Access 2010

I will explain my situation which will hopefully explain what I am trying to do. I have a table that has our staff phone numbers, but I need to be able to see what the next 5 available numbers are.
I have tbl_ext, which is current numbers and tbl_temp, which is used to enter in a "starting" number, dependent on status (managers get 1xxx, sales get 2xxx, etc) . I need to know if it would be possible to "count" the next 5 numbers that are not in tbl_ext and insert these into tbl_temp.
Hopefully this makes some sense, as I am starting to wonder if it is even possible.
The following code will create the next five numbers for extensions that start with '1xxx'. You didn't mention the format of the field (text or number), or if you store Area Code + Exchange + Ext.
You also didn't mntion how many different 'status' there are (1, 2, 3, ...). You can either clone the code and repeat for 1-9 or, you could select the unique high-order digit of all extensions. I can update the answer when you procide more detail.
Public Function Create_Phone_Numbers()
Dim db As Database
Dim rst As Recordset
Dim strSQL As String
Dim i As Integer
Dim iLoop As Integer
Dim iExt As Integer
Dim iStatus As Integer
Set db = CurrentDb
For iStatus = 1 To 9
If iStatus = 999 Then ' Change this line to skip unused numbers
' Do nothing - skip this
Else ' It's a number we want.
strSQL = "SELECT TOP 1 tbl_Ext.PhoneExt FROM tbl_Ext GROUP BY tbl_Ext.PhoneExt HAVING (((tbl_Ext.PhoneExt) Like '" & iStatus & "*')) ORDER BY tbl_Ext.PhoneExt DESC;"
Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)
If Not (rst.EOF And rst.BOF) Then
iExt = rst!PhoneExt
For i = 1 To 5
strSQL = "insert into tbl_Temp (PhoneExt) Select " & iExt + i & " As Expr1;"
db.Execute strSQL
Next i
End If
End If
Next iStatus
rst.Close
Set rst = Nothing
db.Close
Set db = Nothing
End Function

LINQ to SQL, Visual Basic - Listbox Receives the Query NOT the Result

Overview
This is a homework assignment using LINQ to SQL in a Visual Basic application. It is correct in most ways except that I have a partially broken result. Rather than adding the result of my second query to my listbox, my code adds a weird representation of the query itself. Below is a description of the DB, followed by my output (intended and actual), and finally my code. Please point me toward the broken concept so I can figure out what I am missing. Thanks much.
DB info
I am using two tables, called Members and Payments, from one DB. Members has a primary key called ID and also has the fields first_name and last_name. Payments has a foreign key called Members_Id, which is associated to the Member's primary key; Payments also has the payment values under the column Payments.
Output should be like this
Member name = John Smith
$48.00, 10/20/2005
$44.00, 3/11/2006
But is this instead
Member name = SELECT ([t0].[First_Name] + #p1) + [t0].[Last_Name]
AS [value]FROM[dbo].[Members] AS [t0].[ID] = #p0
$48.00, 10/20/2005
$44.00, 3/11/2006
My VB Code
Public Class FormPaymentsGroup
Private db As New KarateClassesDataContext
Private Sub FormPaymentsGroup_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.PaymentsTableAdapter.Fill(Me.KarateDataSet.Payments)
'Group payments by Member_ID (FKey) in the Payments table. (Working fine)
Dim IdQuery = From aMember In db.Payments
Group aMember By aMember.Member_Id
Into MemberPayments = Group
For Each memberID In IdQuery
' Use the passed member_Id to target the row in the Members table and return the first_name & last_name.
' PROBLEM: This only seems to be returning the query itself; not the result.
Dim currMemberID = memberID.Member_Id
Dim nameQuery = From aName In db.Members
Where aName.ID = currMemberID
Select aName.First_Name + " " + aName.Last_Name
Dim currName = nameQuery.ToString ' Load the query result into a portable variable.
LbxMemberPayments.Items.Add("Member name = " & currName) ' PROBLEM: This is where the name SHOULD BE posted to the listbox.
' This is bound to the Members table but directs it based on the above IdQuery.
For Each enteredPayment In memberID.MemberPayments
LbxMemberPayments.Items.Add(vbTab & FormatCurrency(enteredPayment.Amount) & ", " & enteredPayment.Payment_Date)
Next
LbxMemberPayments.Items.Add(vbCr) ' Carriage return formatting
Next
End Sub
End Class
change
Dim currName = nameQuery.ToString
to
Dim currName = nameQuery.FirstOrDefault

Lotus Notes 7 - Auto-calculation for one column from an editable view - InViewEdit event

I have a problem that gives me some headaches lately. I hope I can find a solution with your help.
I have a view : "vwTest" which is embedded on a form. It is an editable view. The view has 3 columns: Number , Cost , Difference. All the 3 columns have as their default values some field names which exist on a form called "fmTest", the field names are: Number , Cost , Difference.
On the main form ( which contains the view ) there is a field ( computed ) called: TotalValue.
The view has 2 actions: AddLine and DeleteLine.
What I want to do is:
Let say TotalValue = 5000
user complete the first line of the view:
Number | Cost | Difference
1 | 50 | 4950 => The 3rd column value to be calculated automatically as the difference between 5000 ( TotalValue ) and 50 ( the value of the 2nd column )
user complete the second line of the view:
2 | 60 | 4890 => the 3rd column value to be calculated automatically as the difference between the last 3rd column value from the view and 60 ( the current value of the 2nd column )
I think that's like a recursive algorithm.
The value of TotalValue exists, it is a Number type field.
Hope to find a solution and resolve this problem! I really appreciate your help and time!
After every save you have to cylce through all entries belonging to "this" main document and recalculate the totals. I assume, that the "lines" are response- documents to the main document and that the Embedded view is categorized by the unid of the main document...
Dim ses as New NotesSession
Dim db as NotesDatabase
Dim viewEmbedded as NotesView
Dim viwNav as NotesViewNavigator
Dim ve as NotesViewEntry
Dim docLine as NotesDocument
Dim docMain as NotesDocument
Dim dblTotal as Double
Set db = ses.CurrentDatabase
Set docMain = ... 'somehow get the main document, therefor I would need your current code
dblTotal = docMain.TotalValue(0)
Set viewEmbedded = db.Getview( "vwTest" )
viewEmbedded.AutoUpdate = False
Set viwNav = viwEmbedded.CreateViewNavFromCategory( docMain.UniversalID )
Set ve = viwNav.getFirst()
While Not ve is Nothing
Set docLine = ve.Document
dblTotal = dblTotal - docLine.Cost(0)
If dblTotal <> docLine.Difference(0) then
docLine.Difference = dblTotal
Call docLine.Save( true, true )
End If
Set ve = viwNav.getnextDocument(ve)
Wend
Why the loop? What if someone modifies the first line after a second one and a third one have been created? then the total for 2, 3 and all subsequent lines has to change.
This code was not typed in Designer and might contain typos. It does NOT contain any error- handling and can produce Replication / Save- Conflicts if not used carefully..
Hope that helps

Excel VBA Macro for Pivot Table with Dynamic Data Range

CODE IS WORKING! THANKS FOR THE HELP!
I am attempting to create a dynamic pivot table that will work on data that varies in the number of rows. Currently, I have 28,300 rows, but this may change daily.
Example of data format as follows:
Case Number Branch Driver
1342 NYC Bob
4532 PHL Jim
7391 CIN John
8251 SAN John
7211 SAN Mary
9121 CLE John
7424 CIN John
Example of finished table:
Driver NYC PHL CIN SAN CLE
Bob 1 0 0 0 0
Jim 0 1 0 0 0
John 0 0 2 1 1
Mary 0 0 0 1 0
Code as follows:
Sub CreateSummaryReportUsingPivot()
' Use a Pivot Table to create a static summary report
' with model going down the rows and regions across
Dim WSD As Worksheet
Dim PTCache As PivotCache
Dim PT As PivotTable
Dim PRange As Range
Dim FinalRow As Long
Dim FinalCol As Long
Set WSD = Worksheets("PivotTable")
'Name active worksheet as "PivotTable"
ActiveSheet.Name = "PivotTable"
' Delete any prior pivot tables
For Each PT In WSD.PivotTables
PT.TableRange2.Clear
Next PT
' Define input area and set up a Pivot Cache
FinalRow = WSD.Cells(Application.Rows.Count, 1).End(xlUp).Row
FinalCol = WSD.Cells(1, Application.Columns.Count). _
End(xlToLeft).Column
Set PRange = WSD.Cells(1, 1).Resize(FinalRow, FinalCol)
Set PTCache = ActiveWorkbook.PivotCaches.Add(SourceType:= _
xlDatabase, SourceData:=PRange)
' Create the Pivot Table from the Pivot Cache
Set PT = PTCache.CreatePivotTable(TableDestination:=WSD. _
Cells(2, FinalCol + 2), TableName:="PivotTable1")
' Turn off updating while building the table
PT.ManualUpdate = True
' Set up the row fields
PT.AddFields RowFields:="Driver", ColumnFields:="Branch"
' Set up the data fields
With PT.PivotFields("Case Number")
.Orientation = xlDataField
.Function = xlCount
.Position = 1
End With
With PT
.ColumnGrand = False
.RowGrand = False
.NullString = "0"
End With
' Calc the pivot table
PT.ManualUpdate = False
PT.ManualUpdate = True
End Sub
They changed the object model for PivotCaches. The method you need in 2007-2010 (that use VBA version 7 instead of version 6) is
PivotCaches.Create
Any reason you are using VBA other than the changing number of rows?
If you are using Excel 2007 / 2010, create a regular table /list (Ctrl-L) from your original data. You can give it a name as well. Then create a Pivot Table and use the table name as the data source. As you add rows your table will expand and you can then just refresh the Pivot Table (F5, or using VBA).
If you are in Excel 2003, you can create dynamic named ranges as well. It's slightly more complex (and a lot more ugly) but I can walk you through it if you are stuck on an older version.

VBA : Querying Access with Excel on server

I'm working with Excel project wich helps to calculate the price of any peace of furniture. The first task is to pick all the materials from the database.
This is the code:
Sub Material_search()
Dim cnt As New ADODB.connection
Dim rst As New ADODB.Recordset
Dim rcArray As Variant
Dim sSQL As String
Dim db_path As String, db_conn As String
Dim item As String
item = Replace(TextBox1.Text, " ", "%") ' Search word
sSQL = "Select Data, NomNr, Preke, Matas, Kaina, Tiek from VazPirkPrekes " & _
"Where VazPirkPrekes.PirkVazID IN (SELECT VazPirkimo.PirkVazID FROM VazPirkimo Where VazPirkimo.Sandelys like '%ALIAVOS')" & _
" and Year(VazPirkPrekes.Data)>=2011 and Preke Like '%" + item + "%' and Kaina > 0" & _
" Order by Preke, Data Desc"
db_path = Sheets("TMP").Range("B6").value
db_conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db_path & ";"
cnt.Open db_conn
rst.Open sSQL, cnt, adOpenForwardOnly, adLockReadOnly
ListBox1.Clear
If Not rst.EOF Then
rcArray = (rst.GetRows)
rcArray = WorksheetFunction.Transpose(rcArray)
Dim a As Variant
With ListBox1
.ColumnCount = 6
.list = rcArray
.ListIndex = -1
End With
End If
rst.Close: Set rst = Nothing
cnt.Close: Set cnt = Nothing
Label4.Caption = UBound(ListBox1.list) + 1
End Sub
recently I came up with some trouble while querying Access mdb file. The problem is when database file is on local disk, the search works very fast, but when i put database file on server, the search takes 10 times longer, which is not acceptable.
Is there any optimisation for this code ? or is it a server problem
Thanks in advance
That query requires Access' database engine retrieve all 190K rows from both tables. It's not surprising it is slow, and the slowness is compounded when the db engine must retrieve 2 * 190K rows across the network.
If TextBox1.Text contains "foo", this is the statement you're asking the db engine to run:
Select Data, NomNr, Preke, Matas, Kaina, Tiek
from VazPirkPrekes
Where
VazPirkPrekes.PirkVazID IN (
SELECT VazPirkimo.PirkVazID
FROM VazPirkimo
Where VazPirkimo.Sandelys like '%ALIAVOS')
and Year(VazPirkPrekes.Data)>=2011
and Preke Like '%foo%'
and Kaina > 0
Order by Preke, Data Desc
The engine must retrieve all 190K rows from the VazPirkimo table before it can determine which of them include Sandelys values which end with "ALIAVOS". If your selection criterion was for values which start with "ALIAVOS", the engine could use an index on Sandelys to limit the number of rows it must retrieve from VazPirkimo. However, since that approach is probably not an option for you, consider adding a numeric field, Sandelys_group, to VazPirkimo and create an index on Sandelys_group. Give all rows where Sandelys ends with "ALIAVOS" the same Sandelys_group number (1). Then your "IN ()" condition could be this:
SELECT VazPirkimo.PirkVazID
FROM VazPirkimo
Where VazPirkimo.Sandelys_group = 1
The index on Sandelys_group will allow the db engine to retrieve only the matching rows, which will hopefully be a small subset of the 190K rows in the table.
There are other changes you can make to speed up your query. Look at this criterion from your WHERE clause:
Year(VazPirkPrekes.Data)>=2011
That forces the db engine to retrieve all 190K rows from VazPirkPrekes before it can determine which of them are from 2011. With an index on Data, this should be much faster:
VazPirkPrekes.Data >= #2011-01-01# AND VazPirkPrekes.Data < #2012-01-01#
This WHERE criterion will be faster with an index on Kaina:
Kaina > 0
Your ORDER BY begs for indexes on Preke and Data.
Order by Preke, Data Desc
Any or all of those changes could help speed up the query, though I don't know by how much. The killer is this WHERE criterion:
Preke Like '%foo%'
The issue here is similar to the problem with the "Sandelys like" comparison. Since this asks for the rows where Preke contains "foo", rather than starts with "foo", the db engine can't take advantage of an index on Preke to retrieve only the matching rows. It must retrieve all 190K VazPirkPrekes rows to figure out which match. Unless you can use a different criterion for this one, you will be limited as to how much you can speed up the query.
Thanks for the optimization tips, but as I said the problem occurs only when I put data base file on server. And there is not much help from optimization. But I thought about other idea.
The search of empty blank "" returns about 40k records (these records covers everything I need) . So I'm going to put all these records on a distinct sheet on workbook_activate event and later do the query only in that sheet.
Sub Database_upload()
Application.DisplayAlerts = False
On Error Resume Next
Sheets("DATA_BASE").Delete
On Error GoTo 0
Application.DisplayAlerts = False
Sheets.Add
ActiveSheet.name = "DATA_BASE"
Sheets("DATA_BASE").Visible = False: Sheets("DARBALAUKIS").activate
Dim cnt As New ADODB.connection
Dim rcArray As Variant
Dim sSQL As String
Dim db_path As String, db_conn As String
Dim item As String
Dim qQt As QueryTable
item = "" 'search for empty blanks
sSQL = "Select Data, NomNr, Preke, Matas, Kaina, Tiek from VazPirkPrekes " & _
"Where VazPirkPrekes.PirkVazID IN (SELECT VazPirkimo.PirkVazID FROM VazPirkimo Where VazPirkimo.Sandelys like '%ALIAVOS')" & _
" and Year(VazPirkPrekes.Data)>=2011 and Preke Like '%" + item + "%' and Kaina > 0" & _
" Order by Preke, Data Desc"
db_path = Sheets("TMP").Range("B6").value
db_conn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & db_path & ";"
db_conn = "ODBC;DSN=MS Access 97 Database;"
db_conn = db_conn & "DBQ=" & db_path
Set qQt = Sheets("Sheet1").QueryTables.Add(connection:=db_conn, Destination:=Sheets("Sheet1").Range("A1"), Sql:=sSQL)
qQt.Refresh BackgroundQuery:=False
End Sub
Results:
Program takes longer on startup, but the search time is acceptable - for me the problem is solved :)

Resources