Writing to %USERPROFILE% issue - vb.net

I have an IO program that I just finished except for one thing. I want the program to automatically detect the User's Profile without hard coding their profile into it. This is what I have now and that works.
My.Computer.FileSystem.WriteAllText("C:\Users\Joshua\Documents\Horoscope\Monthly.txt", Chr(34) & finish & Chr(34), True)
And this is what I want, that doesn't work.
My.Computer.FileSystem.WriteAllText("C:\Users\%USERPROFILE%\Documents\Horoscope\Monthly.txt", Chr(34) & finish & Chr(34), True)
Is there any way to get this to work? The error is telling me that the path doesn't exist. Thanks!

I noticed you're writing to your Documents folder. This folder can be redirected, and so that specific folder name might not even exist for some profiles. You should let the system tell you not only where the user's profile is, but where the user's Documents folder is located, like this:
Dim fileName As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Horoscope", "Monthly.txt")
My.Computer.FileSystem.WriteAllText(fileName, Chr(34) & finish & Chr(34), True)

Use this to build your path:
Path.Combine(Environment.GetEnvironmentVariable("userprofile"), "Documents\Horoscope\Monthly.txt")
Documentation:
Path.Combine
Environment.GetEnvironmentVariable

Related

VBA to save PDF from URL to local folder

I'm trying to cycle through several url's to download the pdf to a local folder.
An example of the url is https://find-energy-certificate.service.gov.uk/energy-certificate/8309-9619-9729-7796-8423?print=true
This is the vb I've written so far.
Dim sveloc As String
Dim svenme As String
Dim url As String
sveloc = Application.ActiveWorkbook.Path & "\Saved EPCs"
i = 7
Do Until sh01.Cells(i, 27) = "" 'all cells in the list are populated with no gaps
url = sh01.Cells(i, 27)
svenme = sh01.Cells(i, 2)
sveloc = sveloc & "\" & svenme & ".pdf"
ThisWorkbook.FollowHyperlink (url)
'code to open and save the pdf goes here
i = i + 1
Loop
Any help gratefully received as I'm really stumped on this one.
TIA.
Inspired by KJ's answer, without error checking etc. Just wanted to illustrate how you'd use shell to automate the entire process.
sveloc = Application.ActiveWorkbook.Path & "\Saved EPCs"
edgePath = Environ$("PROGRAMFILES(X86)") & "\Microsoft\Edge\Application\msedge.exe"
With CreateObject("WScript.Shell")
i = 7
Do Until Len(sh01.Cells(i, 27)) = 0 'all cells in the list are populated with no gaps
On Error Resume Next
.Run """" & edgePath & """ --profile-directory=Default --headless -print-to-pdf=""" & sveloc & "\" & sh01.Cells(i, 2) & ".pdf" & """ """ & sh01.Cells(i, 27) & """", 1, True
On Error GoTo 0
i = i + 1
Loop
End With
No need for VBA but you can use that to alter the variables so using your example from Windows we can run the build pdf at html runtime via Edge:-
"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --profile-directory=Default --headless -print-to-pdf=C:\Users\WDAGUtilityAccount\Desktop\8309-9619-9729-7796-8423.pdf "https://find-energy-certificate.service.gov.uk/energy-certificate/8309-9619-9729-7796-8423?print=true"
and as if by magic the file is in less than a second on my desktop
There is no online pdf it is built by the browser. So it is essential to use the browser. You can remove the print header/footer with one extra switch, but cannot change orientation it will be A4 portrait in UK device.
-print-to-pdf-no-header see currently https://source.chromium.org/chromium/chromium/src/+/main:headless/app/headless_shell_switches.cc;l=60
one other switch may be of value if you only want smaller untagged files
-disable-pdf-tagging see https://source.chromium.org/chromium/chromium/src/+/main:headless/app/headless_shell_switches.cc;l=64
If you try to download without browser printing you will just get the raw HTML as needed for web page printing, thus calling browser remote print as above, will generate the desired "designed for the web" graphics copy.
curl -o test.htm https://find-energy-certificate.service.gov.uk/energy-certificate/8309-9619-9729-7796-8423?print=true
In comments the question was raised how to adapt this approach for change of browser and keeping call simple so I suggest use a cmd or bat file to make that part easier. Thus from vba call something like
Batchfile 8309-9619-9729-7796-8423
#echo off
set "browser=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
set "filedir=C:\Users\WDAGUtilityAccount\Desktop"
set "urlpath=https://find-energy-certificate.service.gov.uk/energy-certificate"
"%browser%" --profile-directory=Default --headless --print-to-pdf="%filedir%\%~1.pdf" -print-to-pdf-no-header "%urlpath%/%~1?print=true"
However, beware calling pdf generations too fast, add a small wait between calls, even on multithreaded CPU writing PDF's at same time often leads to disasters, due to graphics resource conflicts.

Copying Files To a Dynamic Folder Using VBA

I have a VBA code to create a folder every day I run it, based on the date. I use the MkDir for this;
MkDir "C:\Users\Stark\Desktop\Automation\Report" & " " & Format$(Date, "dd-mm-yyyy")
Once this folder is created, I have to copy a few files to this folder on which I will have to work. Since this path keeps changing every time I run, I am not sure how to copy files to the newly created folder in such a case. The FileCopy function throws an error if I use the same path as mentioned above.
FileCopy "C:\Users\Stark\Desktop\Templates\RawData.xlsx", "C:\Users\Stark\Desktop\Automation\Report" & " " & Format$(Date, "dd-mm-yyyy")\RawData.xlsx"
This part throws an error when I want to copy the file from Templates folder to the newly created folder.
Kindly help me.
Your code runs well here, if I correct the concatenation at the end of the FileCopy-line:
\RawData.xlsx" must be concatenated properly using a & (like you do in the other places too):
FileCopy "C:\Users\Stark\Desktop\Templates\RawData.xlsx", "C:\Users\Stark\Desktop\Automation\Report" & " " & Format$(Date, "dd-mm-yyyy") & "\RawData.xlsx"

How to use the relative path in SQL - ODBC?

I have a problem with Excel (ODBC / Access). I would like to refresh data from any folder in my computer. I have file which I use from Desktop, but I would like to refresh data from the same file when it will be move to documents, etc. Please could you provide what I should do?
I have a file connection as below:
DSN=Excel Files;DBQ=C:\Users\User\Desktop\Task1\SalesBudget2018.xlsx;DefaultDir=C:\Users\User\Desktop\Task1;DriverId=1046;MaxBufferSize=2048;PageTimeout=5;
Thank you.
EDIT1: Thank you. I tried use your solution and I received error: "run time error 2147467259 Database or object is read-only", my code below. The bug is related to ".Open" line:
Sub RefreshData()
Dim CreateNew As Object
Dim RunSELECT As Object
Dim Data As String
Dim SQL As String
FolderPath = ActiveWorkbook.path
Path = Left(FolderPath, InStrRev(FolderPath, "\") - 1)
Set CreateNew = CreateObject("ADODB.Connection")
With CreateNew
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=" & Path & "\SalesBudget2018.xlsx" & ";" & "Extended Properties=""Excel 12.0 Xml;HDR=YES;"";"
.Open
End With
'Run SQL
SQL = "SELECT * FROM [twRynki$]"
Set RunSELECT = cn.Execute(SQL)
Do
output = output & RunSELECT(0) & ";" & RunSELECT(1) & ";" & RunSELECT(2) & vbNewLine
Debug.Print RunSELECT(0); ";" & RunSELECT(1) & ";" & RunSELECT(2)
rs.Movenext
Loop Until rs.EOF
End Sub
Your path actually is not relative at all. But ACE/JET data engine does not support relative paths anyway.
A relative path would be
\Data\mydb.mdb
So, above would be one folder up called data from current location. And one folder down using relative would be:
..\Data\mydb.mdb
However, with ACE/Access relative paths are not supported. However, what we do when we want software to work say from the current folder? We simple get and use the full path name ON APPLICATION start up. So, you can get/grab the current folder. In Excel VBA you can use this:
ActiveWorkbook.Path
So above will give you the current path. And thus you use that in code to set the connection string. So, even in access, if we want the software to work in any folder? We simply get/grab the full path name on startup. As a result, the software works in any folder and you effective get relative address in that you "don't care" where the software is placed, since you always get/grab the full path name anyway. So, with above, you could append a folder name called data
ActiveWorkbook.Path & "\Data\Mydb.accdb"
So, from the current workbook location, you could always have a folder called data, and inside that folder you can have your database. So, in effect you do get relative addressing, but you always pulling the full path name of the current workbook as per above.
The end result is you don't miss not having some form of relative addressing since you don't need to with this approach.
The above is for Excel VBA. To get current path from Access VBA? You can use this:
currentproject.Path
So, your connection string to Excel could be this:
dim strExcelPath as string
strExcelPath = CurrentProject.Path & "\Task1\SalesBudget2018.xlsx"
It not clear if the access application is in the SAME folder as task1?
Assuming yes, then this would work:
strExcelPath = CurrentProject.Path & "\SalesBudget2018.xlsx"
So, now the folder can be on the desktop, my documents - it will not matter. You can thus use above as part of your connection string. It not clear if you linking to Excel (linked table), or you using VBA and say ADO code. However, it really don't matter. On application startup, you get the above connection string, check it against the linked table -- if same then do nothing. If different, then you re-link that one table. Thus you ONLY re-link one time if the folder been moved. And no matter where you move the folder? As long as you assume the Excel sheet is in the same folder as the access app, then you good to go. And as noted, you could add a sub folder say ExcelSheets to above. And once again, no matter where you move this folder with the Access part, as long as the sub folder is in the same dir/folder, then this will work - despite you not having relative addressing.

Cannot delete file because it is being used by another process - VB.net

I am converting an TIFF file to a .PNG file in vb.net. First, I save the TIFF file to a specific location (given by NewFileName). Then I convert the file to .PNG using the Bitmap.Save method. Later in my program, I attempt to delete all the .tif files. However, I get an error that says the files are still in use. I have done some research about the reasons for this and I have read that a lot of the errors come from not closing filestream. However, I do not use filestream in my program so I think it is something else. Another possibility that was suggested was that the file was opened twice. I have scoured my code and I am pretty sure the files were never opened, only saved and accessed with the bitmap.Save command. I also downloaded handle.exe and process explorer to find which process was locking the files. Apparently, the files are only in use by the program once I convert them to PNG using the bitmap.save command. Maybe there is a way to close bitmap.Save? Any other suggestions of what to add would be appreciated as well.
objApplication.StartCommand(SolidEdgeConstants.AssemblyCommandConstants.AssemblyViewBottomView)
view = window.View
view.Fit()
withoutExt = "C:\Folder" & "\" & shortForms(12) & FileName
NewFileName = withoutExt & ".tif"
view.SaveAsImage(NewFileName, Width:=width, Height:=height, Resolution:=resolution, ColorDepth:=colorDepth)
System.Drawing.Bitmap.FromFile(NewFileName).Save(withoutExt & ".png", System.Drawing.Imaging.ImageFormat.Png)
Thanks in advance!
I figured it out. All you need is a using statement so that NewFileName is released before I delete it. I changed the code to this and it worked:
view = window.View
view.Fit()
withoutExt = ChosenFile & "\" & shortForms(13) & FileName
NewFileName = withoutExt & ".tif"
view.SaveAsImage(NewFileName, Width:=width, Height:=height, Resolution:=resolution, ColorDepth:=colorDepth)
Using tempImage = System.Drawing.Bitmap.FromFile(NewFileName)
tempImage.Save(withoutExt & ".png", System.Drawing.Imaging.ImageFormat.Png)
End Using
My.Computer.FileSystem.DeleteFile(NewFileName)
Thanks everyone for your help!

Visual Basic.NET Saving Preferences in a .txt or .ini

I want to save my preferences for a program. I just want to know how to do it, since I cant get how to save this file at my documents, because every computer has a different name and username, but using the
My.User.Name
returns 'USERNAME-PC-USERNAME' which doesn't work.
For example, I want the program to create this text file 'CPreferences' at 'C:\Users\'username'\Documents'. And then when the program is re-opened it will automatically load this file into itself, the file will basically contain 2 lines:
Option1:<Value 1>
Option2:<Value 2>
The values will represent choices, ofcourse. So fundamentally, my question is:
1) How to save this file automatically at this user's documents WITHOUT showing a savefiledialog?
2) How to automatically load it if the file there exists?
Thanks,
VB.Net has built-in features for storing and retrieving the user's settings. Just use them. You won't have to worry about how the settings are stored or where the files are. It all just works.
Using something along the lines of string = "----------- " & CurrentTitle & " (" & Now.ToString() & ") User " & Environment.UserName & " on computer " & Environment.UserDomainName & "------------"
will result in
----------- Google - Google Chrome (3/12/2012 2:09:49 AM) User Drise on computer Drise-LAPTOP ------------
Using a streamwriter with filename "C:\users\" & Environment.UserName & "..." should do the trick.
To auto-load the file, check if the file exists and use a streamreader with the same path variable as above, or if not, then set default settings.
For saving to the "My Documents" folder for the current user, this will return the directory path:
My.Computer.FileSystem.SpecialDirectories.MyDocuments
You can also use other items in "special directories" if you want things like the "downloads" or "my pictures" folders, or anything else like that.
I think what you're looking for is user configuration.
You can store settings for users that will be unique to the logged in user.
Use this as a reference for getting started with it:
http://www.codeproject.com/Articles/12252/Application-settings-in-VB-NET-2-0-and-Visual-Stud