Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I need to remove emojis from a csv with 100.000 lines.
Any suggestion?
I've tried some VBA code I found online but didn't work.
Thanks
There is no evidence that you've made an attempt to solve this yourself, and the question is missing several key pieces of information, so I'm not sure if this is actually what you're trying to do.
However, I just happened to be stripping specific characters from "very large" text files, so perhaps this code will help.
QuickReplace in Text File
This reads a text file quickly into a byte array, then dumps into a second byte array, skipping specific characters, then convert the array to a string before saving the file with a new name.
Const fileIn = "x:\myPath\myInputFile.txt"
Const fileOut = "x:\myPath\myOututFile.txt"
Sub stripChars()
Dim bytesIn() As Byte, bytesOut() As Byte
Dim x As Long, y As Long, txtOut As String, fileSize As Long
Debug.Print fileIn & " : Reading Data, ";
Open fileIn For Binary Access Read As #1
fileSize = LOF(1) 'read bytes from file
ReDim bytesIn(fileSize - 1&)
Get #1, , bytesIn
Close #1
Debug.Print "Cleaning, ";
ReDim bytesOut(LBound(bytesIn) To UBound(bytesIn))
For x = LBound(bytesIn) To UBound(bytesIn)
Select Case bytesIn(x)
Case 9, 10, 13 To 126 'retain only specific ASCII characters
bytesOut(y) = bytesIn(x)
y = y + 1
Case Else
'do nothing (skip byte)
End Select
If x / 1000000 = x \ 1000000 Then
DoEvents 'update status bar, every 1m char
Application.StatusBar = "Cleaning: " & Format(x / fileSize, "0.0%")
End If
Next x
ReDim Preserve bytesOut(LBound(bytesOut) To y - 1) 'resize
txtOut = StrConv(bytesOut, vbUnicode) 'convert byte array to string
If Dir(fileOut) <> "" Then Kill fileOut 'delete output file if it exists
Debug.Print "Saving, ";
Open fileOut For Output As #2
Print #2, txtOut 'write to output file
Close #2
Application.StatusBar = "Finished! (Removed " & _
fileSize - FileLen(fileOut) & " bytes)"
Debug.Print "Done."
End Sub
Alternatively there are several worksheet functions that can be used to clean test.
See "Top 10 Ways To Clean Your Data."
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 months ago.
Improve this question
For an example if column value is "ABC 123 981" need to extract only 123... like so if its "456_wert" need to extract only 456 using access VBA code. Can somebody please help on this.
Parse First Consecutive Digits
Sub StrFirstDigitsTEST()
Const pString As String = "a123.456b"
Dim rString As String: rString = StrFirstDigits(pString)
Debug.Print rString, Len(rString)
' Result:
' 123 3
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns a string's ('ParseString') first consecutive digits
' in a string.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function StrFirstDigits(ByVal ParseString As String) As String
Dim ResultString As String
Dim Char As String
Dim FoundDigit As Boolean
Dim n As Long
For n = 1 To Len(ParseString)
Char = Mid(ParseString, n, 1)
If Char Like "#" Then
If Not FoundDigit Then FoundDigit = True
ResultString = ResultString & Char
Else
If FoundDigit Then Exit For
End If
Next n
StrFirstDigits = ResultString
End Function
Parsing strings is fairly simple if data has a consistent structure. Does not seem to be the case here so gets complicated. Your second example could be accomplished with Val("456_wert") but because the first example does not follow same pattern, will require more complex code. Probably have to test each character until a number is encountered. Based on samples provided, something like:
Function GetNumber(varS As Variant) As Variant
Dim x As Integer
GetNumber = Null
If varS & "" Like "*#*" Then
For x = 1 To Len(varS)
If IsNumeric(Mid(varS, x, 1)) Then
GetNumber = Val(Mid(Replace(varS, " ", "|"), x))
Exit For
End If
Next
End If
End Function
Place the procedure in a general module and call it from query or textbox.
SELECT table.*, GetNumber([source field]) AS Nbr FROM table;
=GetNumber([sourcefield])
Shouldn't really be necessary to populate a field in table with this extract, however, the SQL would be:
UPDATE tablename SET fieldname = GetNumber([source field])
I'm trying to get the number of pages in the PDF document. Some of my PDFs are created in Word (saved as PDF), some of them are Xeroxed into the directory (not sure if this matters).
After hours of research I've come to find out that this is easier said than done. The page count rarely comes back giving me the correct number of pages, even though most PDF's do in fact have /Count inside the Binary Code.
For example I've used the following code; it is supposed to open the document in Binary Mode, look for /Count or /N and get the number next to it which is supposed to give me the page count.
Public Sub pagecount(sfilename As String)
On Error GoTo a
Dim nFileNum As Integer
Dim s As String
Dim c As Integer
Dim pos, pos1 As Integer
pos = 0
pos1 = 0
c = 0
' Get an available file number from the system
nFileNum = FreeFile
'OPEN the PDF file in Binary mode
Open sfilename For Binary Lock Read Write As #nFileNum
' Get the data from the file
Do Until EOF(nFileNum)
Input #1, s
c = c + 1
If c <= 10 Then
pos = InStr(s, "/N")
End If
pos1 = InStr(s, "/count")
If pos > 0 Or pos1 > 0 Then
Close #nFileNum
s = Trim(Mid(s, pos, 10))
s = Replace(s, "/N", "")
s = Replace(s, "/count", "")
s = Replace(s, " ", "")
s = Replace(s, "/", "")
For i = 65 To 125
s = Replace(s, Chr(i), "")
Next
pages = Val(Trim(s))
If pages < 0 Then
pages = 1
End If
Close #nFileNum
Exit Sub
End If
'imp only 1000 lines searches
If c >= 1000 Then
GoTo a
End If
Loop
Close #nFileNum
Exit Sub
a:
Close #nFileNum
pages = 1
Exit Sub
End Sub
However, most of the time, it defaults to pages = 1 (under a:).
I've also updated this to 10000 to be sure that it hits the /Count line, yet it still does not give me the correct count.
If c >= 10000 Then
GoTo a
End If
I also came across this reddit
Is there another way to do this, something I can utilize in my app?
Any help is greatly appreciated.
Background:
This is for a legacy vb6 app where I'm attempting to let the user manipulate the PDF files. I added a ListBox that displays all PDF documents in a particular directory. When user double clicks on any one of the files, i display it in a WebBrowser component inside my application.
EDIT: Image containing the BinaryMode line Count for 3 different documents:
I double checked the page count, and /Count displays the correct page count for each of the three documents.
Regular expressions have limits, but I prefer to use them for searching for strings and I think this would be a good place to use one. You may want to play with the pattern because I did this relatively quickly with only a little testing.
Add a reference to Microsoft VBScript Regular Expressions 5.5 to your project. Then you can try the sample code below.
Private Sub Command1_Click()
Dim oRegEx As RegExp
Dim fHndl As Integer
Dim sContents As String
Dim oMatches As MatchCollection
On Error GoTo ErrCommand1_Click
'Open and read in the file
fHndl = FreeFile
Open some pdf file For Binary Access Read As fHndl
sContents = String(LOF(fHndl), vbNull)
Get #fHndl, 1, sContents
Close #fHndl 'We have the file contents so close it
fHndl = 0
'Instantiate and configure the RegEx
Set oRegEx = New RegExp
oRegEx.Global = True
oRegEx.Pattern = "((?:/Count )(\d+))"
Set oMatches = oRegEx.Execute(sContents)
'Look for a match
If oMatches.Count > 0 Then
If oMatches(0).SubMatches.Count > 0 Then
MsgBox CStr(oMatches(0).SubMatches(0)) & " Pages"
End If
End If
Exit Sub
ErrCommand1_Click:
Debug.Print "Error: " & CStr(Err.Number) & ", " & Err.Description
If Not oRegEx Is Nothing Then Set oRegEx = Nothing
If Not oMatches Is Nothing Then Set oMatches = Nothing
End Sub
An explanation of the RegEx pattern:
() creates a group
?: inside the parenthesis makes the group non-capturing
<</Linearized is a literal string
.* greedy quantifier, match any character 0 or more times
/N literal string
\d+ greedy qualtifier, match digits 1 or more times
>> literal string
This is the output of a program.
I have specified what shall be width of each cell in the program and my program shows correct output.
What I want to do is cell content shall be written from right to left. E.g highlighted figure 9983.54 has width of 21. Text file has used first 7 columns. But I want it to use last 7 columns of text file.
Please see expected output image.
I am not getting any clue how to do this. I am not a very professional programmer but I love coding. This text file is used as input to some other program and i am trying to automate writing text file from excel VBA.
Can anyone suggest a way to get this output format?
Here is the code which gave me first output
Option Explicit
Sub CreateFixedWidthFile(strFile As String, ws As Worksheet, s() As Integer)
Dim i As Long, j As Long
Dim strLine As String, strCell As String
'get a freefile
Dim fNum As Long
fNum = FreeFile
'open the textfile
Open strFile For Output As fNum
'loop from first to last row
'use 2 rather than 1 to ignore header row
For i = 1 To ws.Range("a65536").End(xlUp).Row
'new line
strLine = ""
'loop through each field
For j = 0 To UBound(s)
'make sure we only take chars up to length of field (may want to output some sort of error if it is longer than field)
strCell = Left$(ws.Cells(i, j + 1).Value, s(j))
'add on string of spaces with length equal to the difference in length between field length and value length
strLine = strLine & strCell & String$(s(j) - Len(strCell), Chr$(32))
Next j
'write the line to the file
Print #fNum, strLine
Next i
'close the file
Close #fNum
End Sub
'for example the code could be called using:
Sub CreateFile()
Dim sPath As String
sPath = Application.GetSaveAsFilename("", "Text Files,*.txt")
If LCase$(sPath) = "false" Then Exit Sub
'specify the widths of our fields
'the number of columns is the number specified in the line below +1
Dim s(6) As Integer
'starting at 0 specify the width of each column
s(0) = 21
s(1) = 9
s(2) = 15
s(3) = 11
s(4) = 12
s(5) = 10
s(6) = 186
'for example to use 3 columns with field of length 5, 10 and 15 you would use:
'dim s(2) as Integer
's(0)=5
's(1)=10
's(2)=15
'write to file the data from the activesheet
CreateFixedWidthFile sPath, ActiveSheet, s
End Sub
Something like this should work:
x = 9983.54
a = Space(21-Len(CStr(x))) & CStr(x)
Then a will be 14 spaces followed by x:
a = " 9983.54"
Here 21 is the desired column width --- change as necessary. CStr may be unnecessary for non-numeric x.
If you're going to right-justify a lot of different data to different width fields you could write a general purpose function:
Function LeftJust(val As String, width As Integer) As String
LeftJust = Space(width - Len(val)) & val
End Function
The you call it with LeftJust(CStr(9983.54), 21).
Also note that VBA's Print # statement has a Spc(n) parameter that you can use to produce fixed-width output, e.g., Print #fNum, Spc(n); a; before this statement you calculate n: n = 21-Len(CStr(a)).
Hope that helps
I am writing VBA code for an Excel workbook. I would like to be able to open a connection with an Access database, and then import a txt file (pipe delimited) and create a new table in the database from this txt file. I have searched everywhere but to no avail. I have only been able to find VBA code that will accomplish this from within Access itself, rather than from Excel. Please help! Thank you
Google "Open access database from excel VBA" and you'll find lots of resources. Here's the general idea though:
Dim db As Access.Application
Public Sub OpenDB()
Set db = New Access.Application
db.OpenCurrentDatabase "C:\My Documents\db2.mdb"
db.Application.Visible = True
End Sub
You can also use a data access technology like ODBC or ADODB. I'd look into those if you're planning more extensive functionality. Good luck!
I had to do this exact same problem. You have a large problem presented in a small question here, but here is my solution to the hardest hurdle. You first parse each line of the text file into an array:
Function ParseLineEntry(LineEntry As String) As Variant
'Take a text file string and parse it into individual elements in an array.
Dim NumFields As Integer, LastFieldStart As Integer
Dim LineFieldArray() As Variant
Dim i As Long, j As Long
'Determine how many delimitations there are. My data always had the format
'data1|data2|data3|...|dataN|, so there was always at least one field.
NumFields = 0
For I = 1 To Len(LineEntry)
If Mid(LineEntry, i, 1) = "|" Then NumFields = NumFields + 1
Next i
ReDim LineFieldArray(1 To NumFields)
'Parse out each element from the string and assign it into the appropriate array value
LastFieldStart = 1
For i = 1 to NumFields
For j = LastFieldStart To Len(LineEntry)
If Mid(LineEntry, j , 1) = "|" Then
LineFieldArray(i) = Mid(LineEntry, LastFieldStart, j - LastFieldStart)
LastFieldStart = j + 1
Exit For
End If
Next j
Next i
ParseLineEntry = LineFieldArray
End Function
You then use another routine to add the connection in (I am using ADODB). My format for entries was TableName|Field1Value|Field2Value|...|FieldNValue|:
Dim InsertDataCommand as String
'LineArray = array populated by ParseLineEntry
InsertDataCommand = "INSERT INTO " & LineArray(1) & " VALUES ("
For i = 2 To UBound(LineArray)
If i = UBound(LineArray) Then
InsertDataCommand = InsertDataCommand & "'" & LineArray(i) & "'" & ")"
Else
InsertDataCommand = InsertDataCommand & LineArray(i) & ", "
End If
Next i
Just keep in mind that you will have to build some case handling into this. For example, if you have an empty value (e.g. Val1|Val2||Val4) and it is a string, you can enter "" which will already be in the ParseLineEntry array. However, if you are entering this into a number column it will fail on you, you have to insert "Null" instead inside the string. Also, if you are adding any strings with an apostrophe, you will have to change it to a ''. In sum, I had to go through my lines character by character to find these issues, but the concept is demonstrated.
I built the table programmatically too using the same parsing function, but of this .csv format: TableName|Field1Name|Field1Type|Field1Size|...|.
Again, this is a big problem you are tackling, but I hope this answer helps you with the less straight forward parts.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
It seemed like a simple code but I couldn't find it anywhere on the net & I don't know how to write it.
What I want to do is that, say, cell range A1 has a value of "Hey ho he ha".
What I want the code to do is to remove away the rest of the word after the 1st space, so what's left will be with only "Hey".
Thanks!
One line Code...
Range("A1").Value = Split(Range("A1").Value, " ")(0)
Another one line code (based on IolandaAB's answer)
If InStr(1, Range("A1").Value, " ") Then Range("A1").Value = Mid(Range("A1").Value, 1, InStr(1, Range("A1").Value, " ") - 1)
And yet another one line code
If InStr(1, Range("A1").Value, " ") Then Range("A1").Value = Left(Range("A1").Value, InStr(1, Range("A1").Value, " ") - 1)
Take your pick :) My favorite is still the first one.
Sub extract()
Dim myString As String, lung As Integer, i As Integer, pos As Integer
myString = Range("A1").value
lung = Len(myString)
For i = 1 To lung
pos = InStr(i, myString, " ")
If pos <> 0 Then
Exit For
End If
Next i
Range("A1").value = Mid(myString, 1, pos)
End Sub
Loop through the value from your cell and exit when the first space is found in your text. Extract the text before the found space and copy this in your cell.