How to compare the format of text between Excel and Access (like color, bold etc) - ms-access

In fact, what I am doing now is to realize the synchronization of Excel and Sharepoint, which means that Excel can update with the updating of Sharepoint, and the same for the inverse case.
As known, MS 2003 has no problem with this, but MS 2010 can just realize the fonction from Sharepoint -> Excel, but not the inverse way.
So I am thinking to add Access because there exists Access <-> Sharepoint, and so if I can realize la fonction Excel -> Access, that will solve my problem.
I have finished some parts of macros for this, and now I have realized the fundamental fonction of synchronization. However, there are some difficulties in dealing with the format of text. In Sharepoint and Access, to express the color is like this
<div><font color = "#ff0000">TEXT</font></div>, however in excel I have no idea about the expression of the string.
So how to do it? All suggestions or answers will be appreciated.

This is a very broad question and covers alot of possibilities, and this isn't a complete answer, but for comparing HTML to VBA formatting, you would need to individually break down each formatting option and convert it from HTML to VBA and determine the properties applied to the text, just as you stated above. Then you would need individual VBA functions to specify what you want to compare from the text.
That being said, this is just an example of how this can be achieved for font color comparison.
Given:
'example html: <div><font color = "#ff0000">TEXT</font></div>
Dim HTML_text : HTML_text = "<div><font color = '#ff0000'>TEXT</font></div>"
Dim font_color : fontcolor = Mid(HTML_text, instr(HTML_text, "#"), 7)
Would return "#ff0000" as a variable font_color Then you would need the excel function to convert Hex(#FF0000) to RGB (taken from -> Here):
Public Function HEXCOL2RGB(ByVal HexColor As String) As String
Dim Red As String
Dim Green As String
Dim Blue As String
Color = Replace(HexColor, "#", "")
Red = Val("&H" & Mid(HexColor, 1, 2))
Green = Val("&H" & Mid(HexColor, 3, 2))
Blue = Val("&H" & Mid(HexColor, 5, 2))
HEXCOL2RGB = Red & "," & Green & "," & Blue
End Function
Then to extract the fonts RGB in Excel to the RGB you recieved from HTML you would need the following function(taken from -> Here):
Function FontColorRGB(Target As Range) As String
Dim N As Double
N = Target.Font.Color
FontColorRGB = Str(N Mod 256) & "," & Str(Int(N / 256) Mod 256) & "," & Str(Int(N / 256 / 256) Mod 256)
End Function
Then to finally pull it all together, you would utilize both functions:
Dim XLFontClr : XLFontClr = FontColorRGB("A1:A2")
Dim RGB_clr : RGB_clr = HEXCOL2RGB(font_color) 'Returns "Red,Green,Blue" in string form.
If XLFontClr = RGB_clr Then
msgbox "web formatting and excel formatting compared successfully"
End If

Related

Output specific values from a textbox to multiple textboxes in VB

I am using VB with VS2015, and I have a textbox which receives about 40 lines of input from a microprocessor. What I ultimately need to do is display some of the input in multiple textboxes, as well as save those values into a mySQL database. For example, let's say I have:
SensorTypeA_Test
SensorA1_Output: 5.00
SensorA2_Output: 0
SensorA_Test: FAIL
SensorTypeB_Test
SensorB1_Output: 3.50
SensorB2_Output: 3.50
Sensor_Test: Pass
In this case, what I would like to do is basically have 6 textboxes (each with a pre-made label such as Sensor A1) fill with 5.00, 0, FAIL, 3.50, 3.50 and Pass.
As I see it, there are two ways to approach this. First, I could just figure out how to send the values straight to the mySQL database and then pull the needed values into the multiple textboxes. This would be fairly straight forward, but I don't know of a way to send these values directly to the database since they don't have variable names.
The other way is to either parse through the textbox itself or save the input to a file and parse through that. If I did it this way, I would prefer to have each textbox look for the value corresponding to its label, as opposed to filling all of the text boxes sequentially. What I mean by that is if there is a textbox labeled "Sensor A1", it would have its own variable name, say tbSensorA1 and it would look for "SensorA1_Output" and then show the value that comes after the colon, and if there is no value, then just display "N/A" in the textbox. This would also make it really easy to store the values in the database.
So basically, I'm wondering if there are any other ways to do this besides what I proposed, and if not, how can I search a textbox or a text file for a specific phrase and output the values which follow the colon in their corresponding textboxes? Any help is appreciated! Thanks!
Well - lots of ways to do this. I wouldn't recommend trying to do this in the database as databases are not great for parsing, and this feels like logic you should have in your middle or front end anyway. It might be totally front end if this is just really a way to display data you already have.
Here is one approach - create your text boxes that you desire, and in each text boxe's tag property - store a "Prefix" value that can be used to identify if a given sensor data value is appropriate for that text box.
Then you simply loop through each of the text boxes, and sensor data lines, do the comparison, then add the value to the text box if its a match.
Here is sample code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
txtSensor.Text = "SensorTypeA_Test()" & vbCrLf & _
"SensorA1_Output: 5.00" & vbCrLf & _
"SensorA2_Output: 0" & vbCrLf & _
"SensorA_Test: FAIL()" & vbCrLf & _
"SensorTypeB_Test()" & vbCrLf & _
"SensorB1_Output: 3.50" & vbCrLf & _
"SensorB2_Output: 3.50" & vbCrLf & _
"Sensor_Test: Pass()"
End Sub
Private Sub btnPopulate_Click(sender As Object, e As EventArgs) Handles btnPopulate.Click
txtSensorA.Tag = "SensorA"
txtSensorB.Tag = "SensorB"
Dim lstOutputs As New List(Of TextBox)
lstOutputs.Add(txtSensorA)
lstOutputs.Add(txtSensorB)
Dim sensorData() As String = txtSensor.Text.Trim.Split(vbCrLf)
For Each tb In lstOutputs
For Each sline In sensorData
If sline.TrimStart.StartsWith(tb.Tag) Then
UpdateOutputTextBox(tb, sline.Trim)
End If
Next
Next
End Sub
Private Sub UpdateOutputTextBox(tb As TextBox, sLine As String)
Dim sParts() As String = sLine.Split(":")
Dim sData As String = String.Empty
If sParts.Count = 2 Then
sData = sParts(1)
If tb.Text.Length > 0 Then
tb.Text &= (", " & sData.Trim)
Else
tb.Text = sData.Trim
End If
End If
End Sub
And the result...
So you should be able to do something very similar. Hope this helps.

Setting Access Colour Codes in VBA

I'm having trouble setting the back ground colour of a textbox in my Access database. I want to change the colour to red when certain conditions are met.
In design view I've set the textbox's back color property to red and it is shown as '#ED1C24'. When I view the form in Form view the control is correctly shown in the red colour I've chosen.
But when I put this value into my VBA code (Text1.Backcolor = "#ED1C24") I get a type mismatch error.
I've tried changing it to a Hex number (Text1.Backcolor = &HED1C24) but then the control turns blue.
Any help would be appreciated. Thanks.
I wrote a blog about this very problem a while ago which should answer your question.
http://www.jht.co.uk/access-colour-color-codes/
Here's the code:
Public Function HTMLColour(HTMLCode As String, Optional Red As Variant, _
Optional Green As Variant, Optional Blue As Variant) As Long
On Error GoTo HTMLColour_Error
'Converts an HTML colour code number to a long interger
'Also returns the constituent R,G & B components through supplied parameters
Dim intR As Integer, intG As Integer, intB As Integer
Dim strHTML As String
'Strip # prefix if supplied
If Len(HTMLCode) < 6 Then Exit Function
strHTML = Right(HTMLCode, 6)
'Extract R, G, B values
intR = CInt("&H" & Mid(strHTML, 1, 2))
intG = CInt("&H" & Mid(strHTML, 3, 2))
intB = CInt("&H" & Mid(strHTML, 5, 2))
'Return optional parameters
If Not IsMissing(Red) Then Red = intR
If Not IsMissing(Green) Then Green = intG
If Not IsMissing(Blue) Then Blue = intB
'Convert RGB to Long integer
HTMLColour = RGB(intR, intG, intB)
HTMLColour_Exit:
Exit Function
HTMLColour_Error:
MsgBox Err.Description, vbExclamation, "Function HTMLColour"
Resume HTMLColour_Exit
End Function
Hope this helps.
The color code format in VBA is RGB or Long, and not HEX
In your case the easiest way is to call a function that will convert from HEX to Long:
Public Function Color_Hex_To_Long(strColor As String) As Long
Dim iRed As Integer
Dim iGreen As Integer
Dim iBlue As Integer
strColor = Replace(strColor, "#", "")
strColor = Right("000000" & strColor, 6)
iBlue = Val("&H" & Mid(strColor, 1, 2))
iGreen = Val("&H" & Mid(strColor, 3, 2))
iRed = Val("&H" & Mid(strColor, 5, 2))
Color_Hex_To_Long = RGB(iRed, iGreen, iBlue)
End Function
Use it like this :
Text1.BackColor = Color_Hex_To_Long("#ED1C24")
Simply use OnCurrent properties to set your font properties or other properties.
Instead of entering the Hex color codes, easier to use MS Access proprietary codes that are entirely in numbers. Do the easy way. Cheers! Mikey
For MS_ACCESS 2016 the long value seems to be just the .backcolor value, converting the HEX using the functions above won't work.
I'd just create a text box and a label, colour the label as you wish in design view and set the textbox value to txtBlue = lblBlue.backcolour in VBA.
I'm not sure if this is the case in other versions of excel but it seems to be the case in Office 2016.

Better way to implement an Access 2007 "HTML Report"

I need to make a "static html" FAQ-like-document for internal use on a project.
I put all the items in an Access 2007 Database as records (question, answer, category) and then built a report that uses a sub-report to create a table of contents as internal links and then lists all of the questions and answers. This report is a bunch of text-areas with dynamically generated html code(apparently I don't have enough cred to post images yet so http://i115.photobucket.com/albums/n299/SinbadEV/ReportCapture.png)... I just export the report to a text file and then rename it to .html and open it in a browser.
I'm thinking there has to be a less evil way to do this.
I have now used an idea from SinbadEV and awrigley to create professionally looking HTML-reports in MS Access 2007. In my case I had to use yet another trick:
I found out, that due to some bug in MS Access it does not save the report correctly to txt format. Sometimes it drops a lot of information, even though it is displayed on the screen. I have also seen problem, mentioned here that sometimes access mixing lines. It seem to depend on several factors, e.g. whether report and a data span across pages in MS Acess report.
However I found, that exporting to *.rtf does work correctly. Therefore the approach is to craft MS Acess report, which, when saved into text file would create an HTML code (just like described by SinbadEV ), however you 1st need to save it to *rtf. After that you need to use MS Word automation to convert from *.rtf to txt file and to give it .html extention (In reality it does not take too much efforts).
Instead of MS word automation one can probably also use tool like Doxillion Document Converter to convert from rtf to text format from command line.
You can see database with this feature in the Meeting minutes, Issues, Risks, Agreements, Actions, Projects Tracking tool (http://sourceforge.net/projects/miraapt/).
There's an ExportXML method in the Application object, which can export database objects (tables,reports etc.) in XML. You'll need a XSL style sheet or a XSTL document if you want to format it for a browser:
http://msdn.microsoft.com/en-us/library/bb258194(v=office.12).aspx
I'd say this is the "canonical" way to do it. OTOH writing XSL & XSTL isn't like a fun thing to do and if you HTML generator works, then you should simply keep it like it is. (Actually, it's a nice trick IMHO).
I don't see anything inherently "evil" in what you are doing. I wrote an article for (the now defunct magazine) Smart Access that uses a similar technique for a different reason. The HTML report was a by product. Essentially, my technique allows using Access to create very extensive word documents that flow like typed text rather than looking like reports created using boxes.
You can still read the article on MSDN:
Extending Access Reports With Word and HTML
The trick was to generate HTML using a report like you are doing, then using automation, open the .html file in Word and save it as RTF.
We used the technique to create a 300 page directory for the Diocese of York. It worked flawlessly.
Just in case you want to go the VBA way: I wrote a few functions that can make it quite easy:
create queries containing the data you want to output,
then open the query and loop through all records, outputting data to text file using function rRsToXml below.
Option Compare Database
Option Explicit
Function fRsToXml(rs As Recordset, Optional ignorePrefix As String = "zz", _
Optional ignoreNulls As Boolean = False) As String
'<description> Returns an XML string with all fields of the current record,
' using field names as tags.
' Field names starting with "zz" (or other special prefix) are ignored</description>
'<parameters> rs: recordset (byRef, of course)</parameters>
'<author> Patrick Honorez - www.idevlop.com </author>
Dim f As Field, bPrefLen As Byte
Dim strResult As String
bPrefLen = Len(ignorePrefix)
For Each f In rs.Fields
If Left(f.Name, bPrefLen) <> ignorePrefix Then 'zz fields are ignored !
If (Not ignoreNulls) Or (ignoreNulls And Not IsNull(f.Value)) Then
strResult = strResult & xTag(f.Name, f.Value) & vbCrLf
End If
End If
Next f
fRsToXml = strResult
End Function
Function xTag(ByVal sTagName As String, ByVal sValue, Optional SplitLines As Boolean = False) As String
'<description> Create an xml node and returns it as a string </description>
'<parameters> <sTagName> name of the tag </sTagName>
' <sValue> string to embed </sValue>
' <SplitLine> True to include CrLf at the end of each line
' (optional - default = False) </SplitLine></parameters>
'<author> Patrick Honorez - www.idevlop.com </author>
'<note> Make sure sValue does not contains XML forbidden characters ! </note>
'<changelog>
'</changelog>
Dim strNl As String, intAmp
If SplitLines Then
strNl = vbCrLf
Else
strNl = vbNullString
End If
xTag = "<" & sTagName & ">" & strNl & _
Nz(sValue, "") & strNl & _
"</" & sTagName & ">" '& strNl
End Function
Function CleanupStr(strXmlValue) As String
'<description> Replace forbidden char. &'"<> by their Predefined General Entities </description>
'<author> Patrick Honorez - www.idevlop.com </author>
Dim sValue As String
If IsNull(strXmlValue) Then
CleanupStr = ""
Else
sValue = CStr(strXmlValue)
sValue = Replace(sValue, "&", "&") 'do ampersand first !
sValue = Replace(sValue, "'", "&apos;")
sValue = Replace(sValue, """", """)
sValue = Replace(sValue, "<", "<")
sValue = Replace(sValue, ">", ">")
CleanupStr = sValue
End If
End Function
I used to spoof the report generator into making html documents for me but this approach has limitations. Firstly when you run the report, it generates rather ugly html and not a print ready report. There is more work after running the report to transform the report into a nice html document that can be opened in a word processor and then saved as a regular document. LibreOffice often is a better recipient of generated html documents than ms-word but occasionally LibreOffice fails to do the job (for a while it had issues with linked images). Word processors ignore css styles so don't bother with styles, direct formatting still works well, particularly for text is tables. If all the exported data is inside a html table, then use LibreOffice as LibreOffice can generate a table of contents based on h1, h2, h3 headings, whereas ms-word cannot.
These days, I just write the entire report as a procedure in a VBA standard module. I still do not use object oriented code and there is no reason to here. Reports written entirely in VBA can be far more sophisticated that what the standard ms-Access report designer can produce. Report designer reports take a lot of tinkering to get the format just right and this consumes time. For complex reports, the VBA approach is actually faster. A report written in VBA can be run every other second, so it is easy to adjust something such as the column width of a table and to rerun the report to check the output. A html report created with VBA is written out as a html file and the ms-access can issue a shell command to open the report in a web browser. If the browser is already open, the new report opens in a new tab so you can see what the previous version looked like as this version will still be open in another tab.
Write the report in a standard module (not in a form module) and call it from some button-click event on the form. The report should only need to be told what the title is, what the output filename and location are and the data scope that the report should output. The report procedure contains all other logic necessary for creating the report. Below is the calling procedure for triggering a report in one of my applications. The purpose of the calling code is to export a list of geotagged photos in a delimited text file so that I can plot the photo locations on a map. The process for exporting a html file is very similar. Some custom functions are in the code below but the structure should be recognisable.
Private Sub cmdCSV_File_Click()
Dim FolderName As String
Dim FileName As String
Dim ReportTitle As String
Dim SQL As String
Dim FixedFields As String
Dim WhereClause As String
Dim SortOrder As String
'Set destination of exported data
FolderName = InputBox("Please enter name of folder to export to", AppName, mDefaultFolder)
If mPaths.FolderExists(FolderName).Success Then
mDefaultFolder = FolderName 'holds default folder name in case it is needed again
Else
MsgBox "Can't find this folder", vbCritical, AppName
Exit Sub
End If
FileName = CheckTrailingSlash(FolderName) & "PhotoPoints.txt"
'Set Report Title
If Nz(Me.chkAllProjects, 0) Then
ReportTitle = "Photos from all Projects"
ElseIf Nz(Me.SampleID, 0) Then
ReportTitle = "Photos from Sample " & Me.SampleID
ElseIf Nz(Me.SurveyID, 0) Then
ReportTitle = "Photos from Survey " & Me.SurveyID
ElseIf Nz(Me.ProjectID, 0) Then
ReportTitle = "Photos from Project " & Me.ProjectID
Else
MsgBox "Please select a scope before pressing this button", vbExclamation, AppName
Exit Sub
End If
'Update paths to photos
If Have(Me.ProjectID) Then
WhereClause = " (PhotoPath_ProjectID = " & Me.ProjectID & ")" 'also covers sample and survey level selections
Else
WhereClause = " True" 'when all records is selected
End If
Call mPhotos.UpdatePhotoPaths(WhereClause) 'refreshes current paths
'Set fixed parts of SQL statement
FixedFields = "SELECT Photos.*, PhotoPaths.PhotoPath_Alias, PhotoPaths.CurrentPath & Photos.PhotoName AS URL, " _
& "PhotoPaths.CurrentPath & 'Thumbs\' & Photos.PhotoName as Thumb " _
& "FROM Photos INNER JOIN PhotoPaths ON Photos.PhotoPathID = PhotoPaths.PhotoPathID WHERE "
SortOrder = " ORDER BY ProjectID, SurveyID, SampleID, Photo_ID"
'set scope for export
WhereClause = "(((Photos.Latitude) Between -90 And 90) AND ((Photos.Longitude) Between -180 And 180) AND ((Photos.Latitude)<>0) AND ((Photos.Longitude)<>0)) AND " & WhereClause
SQL = FixedFields & WhereClause & SortOrder & ";"
'Export data as a delimited list
FileName = ExportCSV(FileName, SQL)
Call OpenBrowser(FileName)
End Sub
The next bit of code actually writes out the delimited text file (html just has tags instead of pipes). The vertical bar or pipe is used to separate the values rather than a comma in this case as commas may occur in the data. The code works out how many columns there are for itself and puts headings at the top.
Public Function ExportCSV(FileAddress As Variant, SQL As String) As String
If Not gDeveloping Then On Error GoTo procerr
PushStack ("mfiles.ExportCSV")
'Exports a csv file
If Nz(FileAddress, "") = "" Then
ExportCSV = "Failed"
Exit Function
End If
'Create text file:
Dim webfile As Object, w
Set webfile = CreateObject("Scripting.FileSystemObject")
Set w = webfile.CreateTextFile(FileAddress, True)
Dim D As Database, R As Recordset, NumberOfFields As Long, Out As String, i As Long
Set D = CurrentDb()
Set R = D.OpenRecordset(SQL, dbOpenSnapshot)
If R.RecordCount > 0 Then
With R
NumberOfFields = .Fields.Count - 1
'Field headings
For i = 0 To NumberOfFields
If i = 0 Then
Out = .Fields(i).Name
Else
Out = Out & "|" & .Fields(i).Name
End If
Next
w.writeline Out
'Field data
Do Until .EOF
For i = 0 To NumberOfFields
If i = 0 Then
Out = .Fields(i)
Else
Out = Out & "|" & .Fields(i)
End If
Next i
w.writeline Out
.MoveNext
Loop
End With
End If
Set R = Nothing
Set D = Nothing
ExportCSV = FileAddress
exitproc:
PopStack
Exit Function
procerr:
Call NewErrorLog(Err.Number, Err.Description, gCurrentProc, FileAddress & ", " & SQL)
Resume exitproc
End Function
Below is a snippet from the openbrowser function. The rest of the function deals with figuring out where the web browser is, as this varies with the version of windows and whether the browser is 32 or 64 bit.
'Set up preferred browser
If Right(BrowserPath, 9) = "Opera.exe" Then
FilePrefix = "file://localhost/"
ElseIf Right(BrowserPath, 11) = "Firefox.exe" Then
FilePrefix = "file:///"
Else
FilePrefix = ""
End If
'Show report
Instruction = BrowserPath & " " & FilePrefix & WebpageName
TaskSuccessID = Shell(Instruction, vbMaximizedFocus)
This example contains about 90% of the code needed to create a html report that has its scope set by the form that calls it. Hope this gets someone over the hump.

Is there a way to right-align a numeric column in a ListBox

We have a standard Access listbox with multiple columns. Is there a way to have integer or currency columns right aligned?
No. The closest I've seen is JustiCombo which is a database containing functions to center and right justify data for List and Combo Boxes. It can use proportional fonts by analysing the font attributes and character widths. It too stuffs spaces in the front of the fields to make the data appear centre/right justified. It did the best it could but you could see a few jaggies. But then maybe I was being too critical.
Depending on your query the alignment of a column will be inherited from the underlying table. So, go to the table, select the column, center/right/left align it, and then your textbox should have the same alignment. This won't work for calculated fields, but it should for most others.
As far as I'm aware, not in the traditional sense, no. I believe there are some third-party products that might be able to do this, but there's no native ColumnAlignment properties for listboxes in any versions I've used (haven't used Access 2007, though, for what it's worth).
Depending on how you are loading the listbox, you could use a fixed-width font (such as Courier) and left-pad your numbers with the appropriate number of spaces, to emulate right-alignment. It's not ideal, but it may be worth a shot.
Convert the listbox to combobox
Make the combobox that you converted right alignment
Convert it again to listbox
In VB it is:
Format(Format("10000", "0.00%"), "##########") where the number of "#"s are the width of the field in which to right justify the string.
In VBA you can use:
xFormat(Format("10000", "0.00%"), "##########") where
Function xFormat(ByVal s, ByVal width As String) As String
Dim temp As String
Dim deltaL As Integer
deltaL = Len(width) - Len(s)
If deltaL > 0 Then
temp = Space(deltaL) & s
Else
temp = s
End If
xFormat = temp
End Function
The way I solved it was by doing the following:
Go to File -> options -> Client settings -> General alignment
Change the settings to Text Mode, and it worked for me.
I use the following:
Public Function Paddy_Boy(ByVal s As String) As String
Const FillChar As Integer = 160 ' the key to success; this is an unpaddable space
Const MAX_CHARS As Integer = 12 ' the max # of chars in the target column; you could pass this as an arg, but obviously it depends on the data. and i can only get it to work nicely using Courier New.
Dim i As Integer
Dim l As Integer
Dim Z As String
Z = "Paddy_Boy"
Paddy_Boy = s
On Error GoTo Err_Sub
l = Len(s)
i = MAX_CHARS
While (i > l)
Paddy_Boy = Chr(FillChar) & Paddy_Boy
i = i - 1
Wend
Exit_Sub:
Exit Function
Err_Sub:
MsgBox Err.Number & ": " & Err.Description, vbCritical, Z
GoTo Exit_Sub
End Function

Inaccuracies using TextWidth() in VBA

I'm trying to get the length of a string in order to format a report using VBA in Access 2000. Yes I know this old but it's what I've been asked to do. I want to get the width of the string when printed; exactly what TextWidth() is meant to return. What I'm finding is that for strings ranging for 4-20 characters the returned value can range from exactly the right length to the correct length plus about an inch. This is too inaccurate for the formatting I wish to do. Is this common? I can't find any reference to this as a common problem but I've gone over and over the code and I'm fairly certain the function is just inaccurate ratehr than there being a logic problem.
Check the report's FontName and FontSize properties. If they are different than the field you are working with, you'll get wildly different results.
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
MsgBox (Me.FontName & " ," & Me.FontSize)
MsgBox (TextWidth("Test"))
Me.FontName = Me.f2.FontName 'ariel
Me.FontSize = Me.f2.FontSize '8
MsgBox (Me.FontName & " ," & Me.FontSize)
MsgBox (TextWidth("Test"))
Me.FontName = Me.f1.FontName 'ariel
Me.FontSize = Me.f1.FontSize '16
MsgBox (Me.FontName & " ," & Me.FontSize)
MsgBox (TextWidth("Test"))
End Sub
I'm still not sure how to set the report's font name and size though, I don't see anything in it's properties.