I am new to coding, scripting, or even for creating macros. I have been trying to reduce the workload given to me by using VBA and for my coworkers who put the enormous time in repetitions trying to achieve the goal given by managers. I want some help from you guys with some guidance. So I am currently making a basic application in excel for my coworker I have created some code of it to work it will take time but I got one idea I don't know whether it is possible or not. I will give him the workbook once the projects complete from then onwards that workbook will be populated by the data etc I want something like an application to have feature built-in workbook like from one week now I get one idea or a feature I want to add in the workbook how to approach this problem?
I want something like applications that have like pop up and it checks the newer version of the workbook and downloads the code or restructure the code without affecting the data in the workbook.
i'm not an expert nor a newbie !
Simple way is
https://www.mrexcel.com/board/threads/use-vba-to-download-a-file.146856/
Public Sub DownloadInternetFile()
'****************************************************************************************************
' This function is will download a new version of the program. The function uses
' the XMLHTTP object to download files directly from HTTP site. The URL to download
' and the file name to save as are parameters passed by the calling procedure.
'****************************************************************************************************
' Version: 1.0
' Last Modified: 2005-06-16
' Written by: ...
'****************************************************************************************************
Dim StatusMsg As String, FileSize As String, LastModified As String
Dim HeaderData As String, StartTime As Date, EndTime As Date, StateTime As Date
Dim BinaryData As Variant, BinaryData1 As Variant, BinaryData2 As Variant
Dim BinaryData3 As Variant, BinaryData4 As Variant
Dim UnformattedData As String, CurrentState As Variant
Dim FileURL As Variant, SaveFileAs As String, i As Integer, tmp As Double
Const adTypeBinary = 1
Const adSaveCreateNotExist = 1
Const adSaveCreateOverWrite = 2
Set WSH = CreateObject("WScript.Shell")
Set HttpObj = CreateObject("Microsoft.XMLHTTP")
Set BinaryStream = CreateObject("ADODB.Stream")
CurrentState = -1
FileURL = "http://home.comcast.net/~davidawitkin/AdbeRdr60_enu_full.exe"
SaveFileAs = WSH.SpecialFolders("Desktop") & "\" & "AdbeRdr60_enu_full.exe"
StartTime = Now()
HttpObj.Open "GET", FileURL, True
HttpObj.Send
CurrentState = HttpObj.ReadyState
Do Until CurrentState = 4
CurrentState = HttpObj.ReadyState
Select Case CurrentState
Case 1
StateTime = Now()
StatusMsg = StatusMsg & vbNewLine & "State 1: " & StateTime & _
"Size: " & Len(HttpObj.ResponseText)
CurrentState = HttpObj.ReadyState
Case 2
StateTime = Now()
StatusMsg = StatusMsg & vbNewLine & "State 2: " & StateTime & _
"Size: " & Len(HttpObj.ResponseText)
CurrentState = HttpObj.ReadyState
Case 3
StateTime = Now()
StatusMsg = StatusMsg & vbNewLine & "State 3: " & StateTime & _
"Size: " & Len(HttpObj.ResponseText)
CurrentState = HttpObj.ReadyState
End Select
CurrentState = HttpObj.ReadyState
Loop
StateTime = Now()
StatusMsg = StatusMsg & vbNewLine & "State 4: " & StateTime & vbNewLine & _
"Size: " & Len(BinaryData)
MsgBox StatusMsg, 64, "State Change Info"
' Load the binary data into a variable.
BinaryData = HttpObj.ResponseBody
' Specify stream type - we want To save binary data.
BinaryStream.Type = adTypeBinary
' Open the stream And write binary data To the object
BinaryStream.Open
BinaryStream.Write BinaryData
' Save binary data To disk
BinaryStream.SaveToFile SaveFileAs, adSaveCreateOverWrite
EndTime = Now()
' Get header data As a string
UnformattedData = HttpObj.GetResponseHeader("Content-Length")
FileSize = FormatNumber(UnformattedData / 1024000, 1, , -1)
LastModified = HttpObj.GetResponseHeader("Last-Modified")
StatusMsg = "File Size: " & FileSize & " Mbytes" & vbNewLine & _
"Last Modified: " & LastModified & vbNewLine & _
"Binary Data Size: " & BinaryStream.Size
MsgBox StatusMsg, 64, "HeaderData"
End Sub
and then run new file with new code struct!
URL shouldn't to be changed ! in same version , but in any version you can set a different update URL .
Or Option 2 is
Create an Option based user form
that can read options from a plain text
and you can download the txt file and so.
Related
I'm trying to import all data from 3 columns in an access database (.mdb) into my Excel file, which is working, however the numbers that I'm importing aren't coming in correct. You can see in the images supplied what exactly is happening. I am wanting it to import exactly as it is in the database (to 1 decimal place). Now I've tried with changing the numberformat for the Excel columns but of course that only hides the true value with a shortened version so I'd like to avoid doing that.
Dealing with SQL in VBA is something new to me and I don't know Access very well either so I'm wondering if there is something I can add to the query that could affect why the numbers are changing when they get copied into my Excel sheet.
I'm going to be adding a lot more to the code later but just testing connection for now to get it working properly first.
Here is my code (Got the basis for it from a youtube video I found):
Sub GetDataFromAccess()
Application.screenupdating = False
On Error GoTo SubError
Dim db As DAO.Database, rs As DAO.Recordset, xlSheet As Worksheet, recCount As Long, SQL As String, _
TableName As String, FldrLoc As String, FileName As String, ImpSh As Worksheet
Set ImpSh = Sheets("Import")
FldrLoc = ImpSh.Range("D10").Value
FileName = ImpSh.Range("Q15").Value
If Right(FldrLoc, 1) = "\" Then
DbLoc = FldrLoc & FileName
Else
DbLoc = FldrLoc & "\" & FileName
End If
Set xlSheet = Sheets("CAL-53 INC")
If InStr(ImpSh.Range("Q15").Value, ".mdb") > 0 Then
TableName = ImpSh.Range("R5").Value & Left(ImpSh.Range("Q15").Value, Len(ImpSh.Range("Q15")) - 4)
Else
TableName = ImpSh.Range("R5").Value & ImpSh.Range("Q15").Value
End If
xlSheet.Range("G3:I5000").ClearContents
Application.StatusBar = "Connecting to the database..."
Application.Cursor = xlWait
Set db = OpenDatabase(DbLoc)
SQL = "SELECT LRP_CHAINAGE, LEFT_DEPTH, RIGHT_DEPTH" & _
" FROM " & TableName & " ORDER BY LRP_CHAINAGE "
Set rs = db.OpenRecordset(SQL, dbOpenSnapshot)
Application.StatusBar = "Writing to spreadsheet..."
If rs.RecordCount = 0 Then
MsgBox "No data from that table"
GoTo SubExit
Else
rs.MoveLast
recCount = rs.RecordCount
rs.MoveFirst
End If
xlSheet.Range("G3").CopyFromRecordset rs
'xlSheet.Range("G:I").NumberFormat = "0.0"
Application.StatusBar = "Update complete."
SubExit:
On Error Resume Next
Application.Cursor = xlDefault
rs.Close
Set rs = Nothing
Set xlSheet = Nothing
Application.screenupdating = True
Exit Sub
SubError:
Application.StatusBar = ""
MsgBox "Error: " & vbCrLf & Err.Number & " = " & Err.Description
Resume SubExit
End Sub
Here are the pictures of what is in the database and what it's coming in as:
As a quick work around you may set the SQL statement as follows:
SQL = "SELECT Fix(10*[" & TableName & "]![LRP_CHAINAGE])/10 AS LRP_CHAINAGE, Fix(10*[" & TableName & "]![LEFT_DEPTH])/10 AS LEFT_DEPTH, Fix(10*[" & TableName & "]![RIGHT_DEPTH])/10 AS RIGHT_DEPTH" & _
" FROM " & TableName & " ORDER BY LRP_CHAINAGE "
This will give you only one digit after decimal. If you need two digits just change multiplier and divider to 100 :)
SQL = "SELECT LRP_CHAINAGE*10, LEFT_DEPTH*10, RIGHT_DEPTH*10" & _
" FROM " & TableName & " ORDER BY LRP_CHAINAGE "
I'm not running access or windows, but I remember I've done something like this with sql server and excel since vba truncate decimal values
After this query, you can use an update query on the worksheet
UPDATE [IMPORT$]
SET LRP_CHAINAGE=LRP_CHAINAGE/10, LEFT_DEPTH/10, RIGHT_DEPTH/10
Sorry but I was trying to find the answer for hours but could not figure it out.
I tried playing with vbNewLine and vbCrLf but could not make it to work in the function and in the function call.
How do I add a new line with the code below?
Tried this but it did not work:
checker = MessageTimeOut("Underlying raw data in the workbook has been updated." & vbNewLine & "This will close automatically.", "UPDATE RAW DATA - COMPLETED", 5)
Also tried:
checker = MessageTimeOut("Underlying raw data in the workbook has been updated." & vbCrLf & "This will close automatically.", "UPDATE RAW DATA - COMPLETED", 5)
I want the "This will close automatically." shown in a new line.
Function MessageTimeOut(str_message As String, str_title As String, int_seconds As Integer) As Boolean
Dim Shell
Set Shell = CreateObject("WScript.Shell")
Shell.Run "mshta.exe vbscript:close(CreateObject(""WScript.shell"").Popup(""" & str_message & """," & int_seconds & ",""" & str_title & """))"
MessageTimeOut = True
End Function
Sub Some_Sub()
' some lengthy code....
Dim checker As Boolean
checker = MessageTimeOut("Underlying raw data in the workbook has been updated. This will close automatically.", "UPDATE RAW DATA - COMPLETED", 5)
EDIT: My previous answer wasn't using mshta which I think you needed in order to make your message asynchronous and allow your code to continue...
This does the trick:
Sub Test2()
mshta "Me`s`s`age", "test", 5 '<<< all backticks become newlines
Debug.Print "This runs right away"
End Sub
Function mshta(ByVal MessageText As String, Optional ByVal Title As String, _
Optional ByVal PauseTimeSeconds As Integer)
Dim ConfigString As String, WScriptShell
Set WScriptShell = CreateObject("WScript.Shell")
ConfigString = "mshta.exe vbscript:close(CreateObject(""WScript.Shell"").Popup(Replace(""" & MessageText & """,""`"",vbLf)," & PauseTimeSeconds & ",""" & Title & """))"
WScriptShell.Run ConfigString
End Function
I've mixed code and get good results considering that I wish to create csv file without header and for first 12 columns of file.
Also, I've found way to send message about successful creation. My main problem now, is the fact that I can't push code to ask me if file exists, and to create it just after confirmation.
The best solution will be if I may on easier way do next:
create csv for range defined in code
confirm if I wish to overwrite existing file
open file in notepad
Below is code and obviously I need help
Private Sub CommandButton1_Click()
Dim fs As Object, a As Object, i As Integer, s As String, t As String, l As String, mn As String, PathCSV As String, NameCSV As String
PathCSV = "D:\BOM\"
NameCSV = "MMA - " & Format(Date, "mmmm yyyy") & ".csv"
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("D:\BOM\MMA - " & Format(Date, "mmmm yyyy") & ".csv", True)
For r = 5 To Range("A65536").End(xlUp).Row 'start in row 5 due row 1-4 is header
s = ""
c = 1
While c < 13
s = s & Cells(r, c) & ","
c = c + 1
Wend
a.writeline s 'write line
Next r
MsgBox "CSV file successfully save to " & PathCSV & NameCSV
End Sub
try use the snippet
if fs.FileExists(pathcsv & namecsv) then
overwrite = msgbox("overwrite?", vbyesno)
if overwrite = vbno then exit sub
end if
I have some work to complete where I have 9 tabs of data (some of which contain thousands of lines of data). Each tab contains (amongst others) a policy number, a credit and/or a debit number.
Every policy number will have a match somewhere in the tabs containing an equal credit or debit, e.g.
tab 1 will have Policy number 123 and a credit of £100 and
tab 5 will also have policy number 123 with a debit of £100.
What I'm looking to do is, look through each policy number on every tab and find where the opposite amount is located adding the location address to each policy number.
I'm certainly not looking for anyone to create the coding for me, but what I am looking for is advice. I've looked at using loops but feel this may take a very long time to process. I've also looked at Dictionaries but am relatively new to these so am not very confident.
Is what I'm looking for even possible? And if so any ideas where to start or pointers? Any advice is greatly appreciated. Thanks!
Usage Example
#Matt555, You can test the created XML file with the following code to get the sheet names of policy "123" and debit of 100. I tested the code assuming your titles in row A:A contain "policy" and "debit"
#Peh, You are right, xml dom methods aren't used too often within vba. The advantage of using XML in this connex is a great flexibility in searching via XPath as well as performance over huge files. I prefer it even to arrays or dictionaries when filtering unique values. It is possible to return the found item number in node lists without looping through the whole data set ...
Option Explicit
Sub testPolicy()
Dim policy
Dim debit As Double
policy = "123"
debit = "100"
MsgBox "Policy " & policy & " found in " & vbNewLine & _
findSheetName(policy, debit), vbInformation, "Policy " & policy & " in Tabs"
' You can easily split this to an array and analyze the results
End Sub
Function findSheetName(ByVal policy, Optional ByVal debit) As String
' Purpose: Finds Sheet Names where policy AND/OR debit is found
' Note: Assuming your titles in row A:A contain "policy" and "debit"
' You can declare xDoc also after Option Explicit to make it public
Dim xDoc As Object
Dim xNd As Object ' MSXML.IXMDOMNode
Dim xNdList As Object ' MSXML.IXMLDOMNodeList
Dim s As String
' XPath expression
Dim xPth As String
If IsMissing(debit) Then
xPth = "//row[policy=""" & policy & """]"
Else
xPth = "//row[policy=""" & policy & """][debit=""" & debit & """]"
End If
' XML to memory
Set xDoc = CreateObject("MSXML2.Domdocument.6.0")
' allow XPath
xDoc.setProperty "SelectionLanguage", "XPath"
xDoc.validateOnParse = False
' ========
' LOAD XML
' ========
xDoc.Load ThisWorkbook.Path & "\" & "output.xml"
' Loop thru NodeList
Set xNdList = xDoc.DocumentElement.SelectNodes(xPth)
Debug.Print xPth, xNdList.Length
For Each xNd In xNdList
s = s & xNd.ParentNode.NodeName & "|"
Next xNd
Set xDoc = Nothing
findSheetName = s
End Function
You could
a) create an XML file looping through all sheets,
b) open it via load method and
c) perform a simple XPath search (I can give some examples later)
I modified a recent answer (cf. excel-vba-xml-parsing-performance)
to do step "a)" using late binding thus
a) avoiding a reference to the latest MS XML Version Version 6 (msxml6.dll) and
b) getting data over all xheets. XML allows you structured search via XPath over nodes in a logical structure comparable to HTML. The root node in this example is called data, the following nodes are named with the sheets' names and the subsequent nodes get the names in row A:A of each sheet.
A XML file is a simple text file, which you can open by a text editor. Above all you can use VBA XMLDOM methods to analyze or search through the items (nodes). I will give you examples to relating to your question, but give me some time. => see answer "Usage Example", where I explain some Advantages of XML, too (#Peh).
Please pay Attention to the added notes, too.
Option Explicit
Sub xmlExportSheets()
' Zweck: XML Export over all sheets in workbook
' cf. Site: [excel-vba-xml-parsing-performance][1][https://stackoverflow.com/questions/40986395/excel-vba-xml-parsing-performance/40987237#40987237][1]
' Note: pretty printed raw output with line breaks and indentation using an embedded XSLT stylesheet
On Error GoTo ErrHandle
' A. Declarations
' 1 DECLARE XML DOC OBJECT '
' a) Early Binding: VBA REFERENCE MSXML, v6.0 necessary'
' Dim doc As New MSXML2.DOMDocument60, xslDoc As New MSXML2.DOMDocument60, newDoc As New MSXML2.DOMDocument60
' Dim root As IXMLDOMElement, dataNode As IXMLDOMElement, datesNode As IXMLDOMElement, namesNode As IXMLDOMElement
' b) Late Binding XML Files:
Dim doc As Object
Dim xslDoc As Object
Dim newDoc As Object
' c) Late Binding XML Nodes:
Dim root As Object
Dim sh As Object ' xml node containing Sheet Name
Dim dataNode As Object
Dim datesNode As Object
Dim namesnode As Object
' 2 DECLARE other variables
Dim i As Long
Dim j As Long
Dim tmpValue As Variant
Dim tit As String
Dim ws As Worksheet
' B. XML Docs to Memory
Set doc = CreateObject("MSXML2.Domdocument.6.0")
Set xslDoc = CreateObject("MSXML2.Domdocument.6.0")
Set newDoc = CreateObject("MSXML2.Domdocument.6.0")
' C. Set DocumentElement (= root node)'
Set root = doc.createElement("data")
' D. Create Root Node
doc.appendChild root
' ===========================
' ITERATE THROUGH Sheets
' ===========================
For Each ws In ThisWorkbook.Sheets
Set sh = doc.createElement(ws.Name) '
root.appendChild sh
' ===========================
' ITERATE THROUGH ROWS ' A2:NNn
' ===========================
For i = 2 To ws.UsedRange.Rows.Count ' Sheets(1)
' DATA ROW NODE '
Set dataNode = doc.createElement("row") '
sh.appendChild dataNode
' TABLES NODE (orig.: DATES NODE) '
Set datesNode = doc.createElement(ws.Cells(1, 1)) ' Dates
datesNode.Text = ws.Range("A" & i)
dataNode.appendChild datesNode
' NAMES NODE '
For j = 1 To ws.UsedRange.Columns.Count - 1 ' = 12
tit = ws.Cells(1, j + 1)
tmpValue = ws.Cells(i, j + 1)
Set namesnode = doc.createElement(tit)
namesnode.Text = tmpValue
dataNode.appendChild namesnode
Next j
Next i
Next ws
' =============================
' PRETTY PRINT RAW OUTPUT (XSL)
' =============================
xslDoc.LoadXML "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "?>" _
& "<xsl:stylesheet version=" & Chr(34) & "1.0" & Chr(34) _
& " xmlns:xsl=" & Chr(34) & "http://www.w3.org/1999/XSL/Transform" & Chr(34) & ">" _
& "<xsl:strip-space elements=" & Chr(34) & "*" & Chr(34) & " />" _
& "<xsl:output method=" & Chr(34) & "xml" & Chr(34) & " indent=" & Chr(34) & "yes" & Chr(34) & "" _
& " encoding=" & Chr(34) & "UTF-8" & Chr(34) & "/>" _
& " <xsl:template match=" & Chr(34) & "node() | #*" & Chr(34) & ">" _
& " <xsl:copy>" _
& " <xsl:apply-templates select=" & Chr(34) & "node() | #*" & Chr(34) & " />" _
& " </xsl:copy>" _
& " </xsl:template>" _
& "</xsl:stylesheet>"
' XSLT (Transformation)
xslDoc.async = False
doc.transformNodeToObject xslDoc, newDoc
' =================
' Save the XML File
' =================
newDoc.Save ThisWorkbook.Path & "\Output.xml"
MsgBox "Successfully exported Excel data to " & ThisWorkbook.Path & "\Output.XML!", vbInformation
' Regular End of procedure
Exit Sub
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical
Exit Sub
End Sub
Note
Sheet names have to be without spaces
Added Note (important hint):
XML Nodes use titles in first row of every sheet. As the modified procedure gets title names via UsedRange it's important not to have any empty cells in row A:A for this example.
Additional remark
I don't know the reason why my prompt answer (marked as "a") was downgraded by someone. I would find it helpful to argue this :-)
I want to open an attachment from Lotus Notes with VBA.
The Problem is that I don't get the path out of Lotus Notes.
I would be very thankful if you can give me a code, with how I can open this path without hardcoding it.
Here is the complete Code which does not work...
Function OpenURL(URL As String, WindowState As W32_Window_State) As Boolean
'Opens passed URL with default application, or Error Code (<32) upon error
Dim lngHWnd As Long
Dim lngReturn As Long
lngReturn = ShellExecute(lngHWnd, "open", URL, vbNullString, _
vbNullString, WindowState)
OpenURL = (lngReturn > 32)
End Function
Sub OpenLotusNotes()
Dim objNotesSession As Object
Dim objNotesFile As Object
Dim objNotesDocument As Object
Dim objNotesField As Object
Dim objNotesUIWorkSpace As Object
Dim objNotesView As Object
Set objNotesSession = CreateObject("Notes.NotesSession")
Set objNotesFile = objNotesSession.GETDATABASE("ATLAS40", "ACITF\PRODUCTION\USN\ePayable.nsf")
'("Server", "Datenbank")
Set objNotesUIWorkSpace = CreateObject("Notes.NotesUIWorkSpace")
Set i = Sheet1.Range("B20")
Dim DocNum As Variant
Dim DocName As Variant
Set objNotesView = objNotesFile.GetView("1.CheckView")
Set objNotesDocument = objNotesView.GetFirstDocument
Dim body As Variant
Dim ms As String
ms = ""
If Not objNotesDocument Is Nothing Then
'initial set
DocNum = objNotesDocument.InvoiceNumber
DocName = objNotesDocument.InvoiceDocumentNumber
Dim DocFound As Boolean
DocFound = False
While Not DocFound = True
DocNum = objNotesDocument.InvoiceNumber
DocName = objNotesDocument.InvoiceDocumentNumber
If DocNum(0) = i Then
ms = "You are about to open the attachement located in " & DocNum(0) & " " & DocName(0) & " in The Way we do things database from Database Server " & objNotesFile.server & " with Database File name " & objNotesFile.Filename & "."
MsgBox (ms)
DocFound = True
Set body = objNotesDocument.getfirstitem("$FILE")
'subject der mail ermitteln
For Each obj In body.embeddedobjects
'MsgBox (Environ("TEMP") & "\" & obj.Name)
'MsgBox (obj.Name)
Call obj.ExtractFile(Environ("TEMP") & "\" & obj.Name)
OpenURL "file://" & Environ("TEMP") & "\" & obj.Name, Show_Maximized
Next
End If
Set objNotesDocument = objNotesView.GetNextDocument(objNotesDocument)
Wend
End If
You can't open the file by accessing the $File item, so even if you had the correct syntax (using GetFirstItem("$File)) it would still not work.
You need to use objNotesDocument.EmbeddedObjects() This will return an array of NotesEmbeddedObject objects. If there's only one file attachment in the document, there will be only one element in the array. You can use the ExtractFile method of the NotesEmbeddedObject class to save a copy of the file to the filesystem, and you can open it from there.