How to Split a String and Store in MS Access table - string

I would like to be able to split a string of text that has been entered into a textbox on a MS Access form and store the split strings as separate records under the same field. This is the code I have so far, but I keep running into problems at every corner. I'm fairly new to this, but have been learning quickly. Any help is appreciated.
Here is what I'd like to accomplish: If I enter the following text into a text box ("this is a sentence") and click submit. I would like each other the words to be stored as individual records under a common field. Seems simple, but it's causing quite a few headaches.
Private Sub Submit_Click()
Dim SetDBConnection As ADODB.Connection
Set SetDBConnection = CurrentProject.Connection
Dim strInsertRecord As String
Dim strNewPhrase As String
Dim strStorePhrase As String
strNewPhrase = textPhrase
strStorePhrase = Split(NewPhrase)
strInsertRecord = "INSERT INTO [FieldSplice] (words) VALUES (" & strStorePhrase & ")"
SetDBConnection.Execute strInsertRecord
textPhrase.Value = Null
End Sub

I'm a little unclear on why you have the ADODB connection... is this connecting to an external database? If so, that makes sense, but then you are missing some code to get the insert to work properly.
If this is just an internal (native) Access table, then I don't think you need any of that. Here is a simple example of how you would take a string, split it into words (based on a space) and then insert those into your table:
Dim textPhrase As String
Dim words() As String
Dim i As Integer
textPhrase = "This is a test"
words = Split(textPhrase, " ")
sql = "parameters P1 text; INSERT INTO [FieldSplice] (words) VALUES ([P1])"
Set query = CurrentDb.CreateQueryDef("FsInsert", sql)
For i = LBound(words) To UBound(words)
query.Parameters("P1").Value = words(i)
query.Execute
Next i
CurrentDb.QueryDefs.Delete ("FsInsert")
One other note of interest -- you don't need to declare the insert each time. You can set a parameter, assign values to the parameter and execute the insert command multiple times. This is included in my example above.
Your code was trying to say:
insert into [table] (field) values ("value1", "value2", "value3")
Which you can't do. That has to be done as three inserts, unless your database supports array inserts (Oracle, for example).
The multiple fields only works like this:
insert into [table] (field1, field2) values ("value1", "value2")
Where each value corresponds to a column in the table.

Related

Filter phone numbers from open text field - Power BI, excel, VBA

I have a text field in a table where I need to substitute phone numbers where applicable.
For example the text field could have:
Call me on 08588812885 immediately
Call me on 07525812845
I need assistance please contact me
Good service
Sometimes a phone number will be in the text but not always and the phone number entered will always be different.
Is there a measure to use to replace the phone numbers with no text.
Ideally the solution would be Power BI, but can also be done in the raw data using excel or VBA
Regular expression in VBA (excel) or Python (Power BI) is a straightforward solution.
I have never used PowerBI with Python before but manage to make following python script.
In PowerBI transformation steps I created a new column that would copy [message] columns and named it [noPhoneNumber], then next step ran this python script
import re
def removePhone(x):
return re.sub('\d{10,11}', "**number removed**", x)
length = len(dataset["noPhoneNumber"])
for iRow in range(length):
dataset["noPhoneNumber"][iRow] = removePhone(dataset["noPhoneNumber"][iRow])
so column "noPhoneNumber"
Call me on 08588812885 immediately
Call me on 07525812845
I need assistance please contact me
Good service
becomes
Call me on **number removed** immediately
Call me on **number removed**
I need assistance please contact me
Good service
In VBA Preferable create UDF (user defined function) and don't create a subroutine, that would be too error prone for this kind of problem.
[Added]
If you need to make a Excel based solution, you can create a UDF function like so:
(remember early binding to import of VBScript_RegExp_55.RegExp in excel)
Function removePhoneNumber(text As String, Optional replacement As String = "**number removed**") As String
Dim regex As New RegExp
regex.Pattern = "\d{10,11}"
removePhoneNumber = regex.Replace(text, replacement)
End Function
...and then use excel function like so:
=removePhoneNumber(A2),
=removePhoneNumber(A3)
and so on...
A simple VBA function alternative
Function removePhone(s As String) As String
Const DELIM As String = " "
Dim i As Long, tokens As Variant
tokens = Split(s, DELIM)
For i = LBound(tokens) To UBound(tokens)
If IsNumeric(tokens(i)) Then
tokens(i) = "*Removed*" ' << change to your needs
Exit For ' assuming a single phone number per string
End If
Next
removePhone = Join(tokens, DELIM)
End Function
You can do this in Power Query. Create a custom column with this below code. I have considered the column name is Comments but please adjust this with your column name.
if Text.Length(Text.Select([comments], {"0".."9"})) = 11
then
Text.Replace(
[comments],
Text.Select([comments], {"0".."9"}),
""
)
else [comments]
Here is the output below. You can also replace phone numbers with other text like #### to make is anonymous.
NOTE
This will only work if there are only 1 number in the string with length 11 (You can adjust the length in code as per requirement).
This will Not work if there are more than one Numbers in the string.
If there are 1 number in the string but length not equal 11, this will keep the whole string as original.

how to import excel to datagrid, then filter by db values

my question about import excel to datagridview but there is an extra case.
I have also a oledb database with store code and store names.
I want it to show only store codes from db that are in the database after imported.
my codes here;
Dim conn As OleDbConnection
Dim dtr As OleDbDataReader
Dim dta As OleDbDataAdapter
Dim cmd As OleDbCommand
Dim dts As DataSet
Dim excel As String
Dim OpenFileDialog As New OpenFileDialog
OpenFileDialog1.FileName = ""
OpenFileDialog1.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.Desktop
OpenFileDialog1.Filter = "All Files (*.*)|*.*|Excel files (*.xlsx)|*.xlsx|CSV Files (*.csv)|*.csv|XLS Files (*.xls)|*xls"
If (OpenFileDialog1.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK) Then
DataGridView1.Columns.Clear()
Dim fi As New FileInfo(OpenFileDialog1.FileName)
Dim FileName As String = OpenFileDialog1.FileName
excel = fi.FullName
conn = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excel + ";Extended Properties=Excel 12.0;")
dta = New OleDbDataAdapter("Select * From [Sheet1$]", conn)
dts = New DataSet
dta.Fill(dts, "[Sheet1$]")
DataGridView1.DataSource = dts
DataGridView1.DataMember = "[Sheet1$]"
conn.Close()
End If
firstly sorry for my terrible english :)
images as follows;
Main Form
Store List Form
I want only the ones in the store list to be displayed in datagrid.. :\
It's not exactly clear what your current presentation/display looks like, what the problem is, and what your desired presentation/display should look like. But you have asked about selecting only one part of the data you are importing, which is presumably found in only one column of the imported Excel data.
When the datatable is created, it has the columns and rows from the Excel worksheet. The columns will be data from the first row, and the rows will be the records from the succeeding rows in the worksheet. You can access both the header data and the row data easily. The code below is VERY rough but for you to see how to gain access to the data in the datatable which you have already very successfully imported in the limited code shown above.
Dim columns = datatable.Columns
Dim rows = datatable.Rows
Dim columns1 = columns(0)
Dim rows1 = rows(0)
Dim element1 = rows1(0)
Columns will have all the headers, so you can locate the column with the store codes or store names. Then the rows will have the data for each store. So above, rows1 is the first row of data and element1 is the data in that row from columns1, and so on. The (0) is the index into the respective collections.
You will, of course, have to write code to extract the data you want and if necessary eliminate duplicates, but the data is all there already.
Hopefully getting the data into a list and then sorting, filtering and selecting the data should be relatively straightforward, but if not, add a comment. That's kind of a different problem. You asked about getting only the store codes.
Added: Based on your additional images and explanation, you are looking to perform an SQL INNER JOIN operation. From the w3schools.com page on SQL INNER JOIN, "The INNER JOIN keyword selects all rows from both tables as long as there is a match between the columns." This is something you will have to study and learn, but it should provide what you need in this case. You will need to define and construct both tables and then perform the JOIN.
And, by the way, you could also follow the link provided in the first comment by T.S., and if that solves your problem, it's a far simpler solution.

Why does Excel treat double spaces as a comma?

I wrote an export to CSV file in my vb.net application, and I then exported it into Outlook.
The issue I've got, is that when the CSV file is being written, my code is checking for a comma in the current field, but while doing this, it also mistakes a double space for a comma, or space followed by 'Enter' key being pressed (for multiline textboxes)
An example would be if in the notes section of the customer, there is 4 lines of text, and one ends in a space - The user has then pressed enter to go to the next line, however the program is taking the next line of text and creating a new record for it, as it thinks it's a comma...
What is the reason for this? This means that data has to be super validated (ie checking for no double spaces etc) before it can be exported, which is far too time consuming.
Hopefully this makes sense!
This is the code:
Dim result As Boolean = True
Try
Dim sb As New StringBuilder()
Dim separator As String = ","
Dim group As String = """"
Dim newLine As String = Environment.NewLine
For Each column As DataColumn In dtable.Columns
sb.Append(wrapValue(column.ColumnName, group, separator) & separator)
Next
sb.Append(newLine)
For Each row As DataRow In dtable.Rows
For Each col As DataColumn In dtable.Columns
sb.Append(wrapValue(row(col).ToString(), group, separator) & separator)
Next
sb.Append(newLine)
Next
The code for wrapValue
Function wrapValue(value As String, group As String, separator As String) As String
If value.Contains(separator) Then
If value.Contains(group) Then
value = value.Replace(group, group + group)
End If
value = group & value & group
End If
Return value
End Function
Based on the fact that it's shortening it by 430 lines, I'd suggest it's something to do with the fact you're adding a load of "" before and after the value variable.
If it's removing a value at the start, then it will be removing a " before the first column header. As to why it's importing one record as you mentioned in the comments, I'm not entirely sure, however, I would suggest the issue lies in your wrapValue code.
Can you try changing
value = group & value & group
to
value = value
and see if that changes anything?

VBA Special characters U+2264 and U+2265

I have a frustrating problem. I have a string containg other characters that are not in this list (check link). My string represents a SQL Query.
This is an example of what my string can contain: INSERT INTO test (description) VALUES ('≤ ≥ >= <=')
When I check the database, the row is inserted successfully, but the characters "≤" and "≥" are replaced with "=" character.
In the database the string in description column looks like "= = >= <=".
For the most characters I can get a character code. I googled a character code for those two symbols, but I didn't find one. My goal is to check if my string contains this two characters , and afterwards replace them with ">=" and "<="
===Later Edit===
I have tried to check every character in a for loop;
tmp = Mid$(str, i, 1)
tmp will have the value "=" when my for loop reaches the "≤" character, so Excel cannot read this "≤" character in a VB string, then when I'm checking for character code I get the code for "=" (Chr(61))
Are you able to figure out what the character codes for both "≤" and "≥" in your database character set are? if so then maybe try replacing both characters in your query string with chrw(character_code).
I have just tested something along the lines of what you are trying to do using Excel as my database - and it looks to work fine.
Edit: assuming you are still stuck and looking for assistance here - could you confirm what database you are working with, and any type information setting for the "description" field you are looking to insert your string into?
Edit2: I am not familiar with SQL server, but isn't your "description" field set up to be of a certain data type? if so what is it and does it support unicode characters? ncharvar, nchar seem to be examples of sql server data types that support Unicode.
It sounds like you may also want to try and add an "N" prefix to the value in your query string - see
Do I have use the prefix N in the "insert into" statement for unicode? &
how to insert unicode text to SQL Server from query window
Edit3: varchar won't qualify for proper rendering of Unicode - see here What is the difference between varchar and nvarchar?. Can you switch to nvarchar? as mentionned above, you may also want to prefix the values in your query string with 'N' for full effect
Edit4: I can't speak much more about sqlserver, but what you are looking at here is how VBA displays the character, not at how it actually stores it in memory - which is the bottom line. VBA won't display "≤" properly since it doesn't support the Unicode character set. However, it may - and it does - store the binary representation correctly.
For any evidence of this, just try and paste back the character to another cell in Excel from VBA, and you will retrieve the original character - or look at the binary representation in VBA:
Sub test()
Dim s As String
Dim B() As Byte
'8804 is "≤" character in Excel character set
s = ChrW(8804)
'Assign memory representation of s to byte array B
B = s
'This loop prints "100" and "34", respectively the low and high bytes of s coding in memory
'representing binary value 0010 0010 0110 0100 ie 8804
For i = LBound(B) To UBound(B)
Debug.Print B(i)
Next i
'This prints "=" because VBA can not render character code 8804 properly
Debug.Print s
End Sub
If I copy your text INSERT INTO test (description) VALUES ('≤ ≥ >= <=') and paste it into the VBA editor, it becomes INSERT INTO test (description) VALUES ('= = >= <=').
If I paste that text into a Excel cell or an Access table's text field, it pastes "correctly".
This seems to be a matter of character code supported, and I suggest you have a look at this SO question.
But where in you program does that string come from, since it cannot be typed in VBA ??
Edit: I jus gave it a try with the below code, and it works like a charm for transferring your exotic characters from the worksheet to a table !
Sub test1()
Dim db As Object, rs As Object, cn As Object
Set cn = CreateObject("DAO.DBEngine.120")
Set db = cn.OpenDatabase("P:\Database1.accdb")
Set rs = db.OpenRecordset("table1")
With rs
.addnew
.Fields(0) = Range("d5").Value
.Update
End With
End Sub

Using multiple values field in Lotus Notes

I am trying to write a logging system for a form in Lotus Notes but I am at the part where I am not sure how I can append the information about the fields that are changed in the log fields. There are 3 fields that I use Log_Date (date), Log_User and Log_Actions (Text, allow multiple values).
I thought if I add comma to the log field it will create a new line when displaying the form but I am still getting a type mismatch on the case 2 line.
How can I append the new values to the log fields?
Sub Querysave(Source As Notesuidocument, Continue As Variant)
' Compare the values in the form after it is saved with its original values when the document is not a new document.
Dim doc As NotesDocument
Set doc = Source.Document
Dim session As New NotesSession
Dim user As String
user = session.CommonUserName
If newDoc Then
doc.Log_Date = Now()
doc.Log_User = user
doc.Log_Actions = "New document created."
Else
' Load fields value to the array
lastValues(0) = doc.QCR_No(0)
lastValues(1) = doc.QCR_Mobile_Item_No(0)
lastValues(2) = doc.QCR_Qty(0)
' Compared each value in the array to see if there is any difference
Dim i As Integer
For i = 0 To 2
If lastValues(i) <> originalValues(i) Then
Select Case i
Case 2 : doc.Log_Actions = doc.Log_Actions & "," & "Field QCR_Qty is changed"
End Select
End If
Next
End If
End Sub
doc.Log_Actions returns the notesitem. To access the value you need to use doc.Log_Actions(0)
In LotusScript back-end classes (e.g. NotesDocument, NotesItem), a multi-valued field is represented by an array with one value per element of the array. For setting the value of a field, doc.Log_Actions is shorthand (they call it 'extended syntax' in the Domino Designer help) for assigning the first (i.e., zero subscript) element of the array, but that does not work for getting the value. To get the first value, you have to use doc.Log_Actions(0). To get or set the second value, you have to use doc.Log_Actions(1).
So, your Case 2 code could look like this:
doc.Log_Actions(1) = "Field QCR_Qty is changed"
My guess, however, is that you really want to be able to continually append to the end of the list of values each time this code runs. You are also going to want your code to be robust and not blow up on you if (for any reason!) the Log_Actions item does not exist in the document. For that, you are going to want to do this:
dim actionsItem as NotesItem
if doc.hasItem("Log_Actions") then
set actionsItem = doc.getFirstItem("Log_Actions")
call actionsItem.AppendToTextList("Field QCR_Qty is changed")
end if
Or,
If (Not doc.HasItem("LogActions")) Then
doc.LogActions = "Field QCR_Qty is changed"
Else
doc.LogActions = ArrayAppend(doc.LogActions,"Field QCR_Qty is changed")
End If
This is equivalent to the NotesItem method by rhsatrhs, which you use is matter of preference.

Resources