Bitmap issue - parameter is not valid & out of memory - exception

I have a vb.net program that tries to take a bunch of images and change the resolution to a smaller size. My program tries to loop through all the images to accomplish this using this code below. I've posted both the function and the button click that calls it. It will go through 27 images fine but on the 28th will error out with "parameter is not valid".
Friend Shared Function SetResolution(ByVal sourceImage As Image, ByVal resolution As Integer, ByVal strFullPath As String) As Image
Try
Dim reduction As Double = resolution / CInt(sourceImage.HorizontalResolution)
Using newImage As New Bitmap(sourceImage.Width, sourceImage.Height, sourceImage.PixelFormat)
newImage.SetResolution(resolution, resolution)
Dim outImage As New Bitmap(sourceImage, CInt(sourceImage.Width * reduction), CInt(sourceImage.Height * reduction))
Using g As Graphics = Graphics.FromImage(newImage)
g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
g.DrawImage(outImage, 0, 0)
g.Dispose()
End Using
newImage.Dispose()
Return outImage
End Using
Catch ex As Exception
MsgBox("An error occurred with the SetResolution function - " & ex.Message)
End Try
End Function
Private Sub btnSaveImages_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSaveImages.Click
Dim S As String
Dim Box As MsgBoxResult = MsgBox("Any previous images saved to this location will be overwritten. Are you sure you want to save these images?", MsgBoxStyle.YesNo)
Dim strFolderPath As String = ""
Dim strFolderReportPath As String = txtBrowse.Text & "\Report"
'Try
'the Report folder may not exist. Create it if needed.
If Not Directory.Exists(strFolderReportPath) Then
Directory.CreateDirectory(strFolderReportPath)
Else
'if it does exist then we need to either delete the folder or clean out all the files.
Dim downloadedMessageInfo As System.IO.DirectoryInfo = New DirectoryInfo(strFolderReportPath)
For Each file As FileInfo In downloadedMessageInfo.GetFiles()
file.Delete()
Next
For Each dir As DirectoryInfo In downloadedMessageInfo.GetDirectories()
dir.Delete(True)
Next
End If
If Box = MsgBoxResult.Yes Then
If lstSelectedImages.Items.Count <> 0 Then
For Each S In lstSelectedImages.Items
'MessageBox.Show(S)
Dim image1 As Image = Image.FromFile(S)
Dim strFilePath As String = Path.GetDirectoryName(S)
strFolderPath = Path.GetDirectoryName(S)
Dim strFileName As String = Path.GetFileName(S)
Dim strNewFolder As String = strFilePath & "\Report\"
strFileName = strFileName.Replace(".", "-Report.")
Dim strFullPath As String = strFilePath & "\Report\" & strFileName
image1 = SetResolution(image1, 50, strFilePath & "\" & Path.GetFileName(S))
'the Report folder may not exist. Create it if needed
If Not Directory.Exists(strNewFolder) Then
Directory.CreateDirectory(strNewFolder)
End If
image1.Save(strFullPath, System.Drawing.Imaging.ImageFormat.Jpeg)
image1.Dispose()
image1 = Nothing
Next
Dim di As New DirectoryInfo(strFolderReportPath)
'PopulateReportViewer(lstSelectedImages)
PopulateReportViewerByDir(di)
lblImageFolderLocation.Text = "Image Location: " & strFolderReportPath
MsgBox("Images saved to " & strFolderReportPath)
Else
MsgBox("Please select images to be saved into the Selected Images list box", MsgBoxStyle.Information)
End If
Else
End If
tbSelectCompressImages.TabPages.Add(TabPage2)
tbSelectCompressImages.SelectedIndex = 1
'Catch ex As Exception
' MsgBox("An error occurred with the Save Images button - " & ex.Message)
'End Try
End Sub
So, I was pretty stumped with that and decided to make a small change to how the bitmap was created to below. I was able to get 28 images saved again but this time received an out of memory error for the Graphics.FromImage line.
Dim newimage As Bitmap = DirectCast(Image.FromFile(strPath), Bitmap)
Does anyone know why this is occurring looking at my code. Or, is there code somewhere that I can get to set the resolution for an image so that the memory stamp is much smaller?
thanks.

but we can't see what you do with sourceImage and outImage.
image1 = SetResolution(image1, 50, strFilePath & "\" & Path.GetFileName(S))
You are re-assigning the image1 variable with this statement. Problem is, you never disposed the original image1. It is also a major guess why you are passing a path name, the method doesn't use it at all. So somewhat more sane code that doesn't forget to dispose ought to look like this:
Dim newImage = SetResolution(image1, 50)
image1.Dispose()
image1 = newImage

Related

MSAccess VBA to Save a Single Attachment to a Folder

I'm really new to Access so I haven't heard of most of the commands for Access VBA, but I am pretty familiar with Excel VBA.
What I'm trying to do is save the attachment that was just entered into a table through a form. I've been looking at some examples online and trying to get it to work for me but the code is not moving the file to the folder. I do not get a debug error though.
Here is my current code. I know it is set to loop right now, where really I just want the last attachment in the table each time, but I don't know how to get only the last attachment. Either way, this current code doesn't move ANY attachments.
Private Sub cmdAddRecord_Click()
If MsgBox("Adding a new record will save the current form. You will not be able to edit this credit request. Would you like to continue?", vbQuestion + vbYesNo, "Save current record and open new form") = vbYes Then
MkDir "C:\Users\username\Desktop\IC Transfer Back Up Attachments\" & Me.txtRequestID & "-" & "Back Up Attachments" & " " & Format(Date, "MMDDYY")
DoCmd.RunCommand acCmdSaveRecord
Dim SaveFolder As String
SaveFolder = "C:\Users\username\Desktop\IC Transfer Back Up Attachments\" & Me.txtRequestID & "-" & "Back Up Attachments" & " " & Format(Date, "MMDDYY")
Dim rsParent As DAO.Recordset2
Dim rsChild As DAO.Recordset2
Set rsParent = CurrentDb.OpenRecordset("SELECT * FROM tblICTRequested")
Set rsChild = rsParent.Fields("BackUpAttachments").Value
Do Until rsChild.EOF
rsChild.Fields("FileData").SaveToFile SaveFolder
rsChild.MoveNext
Loop
DoCmd.RunCommand acCmdCloseWindow
DoCmd.OpenForm "frmICTRequested"
End If
End Sub
Most of this seems to make sense to me, but I'm not sure what I should put in the .Fields("FileData").SaveToFile line, since I don't have a field named "FileData" but I've tried all my existing fields to no avail.
For reference, here are some of the online links I have reviewed:
https://www.experts-exchange.com/questions/29005769/MS-Access-attachment-file.html
https://msdn.microsoft.com/en-us/library/office/ff191852.aspx
https://access-programmers.co.uk/forums/showthread.php?t=282135
Any tips? Much appreciated!
You're very close. I use a function like this:
Public Function SaveFileToDisk(FileName As String, FileData As DAO.Field2, Optional saveToFolder As String) As String
Dim templatePath As String
If saveToFolder = "" Or Not fso.FolderExists(saveToFolder) Then
saveToFolder = Environ("temp")
End If
templatePath = GetAvailableFileName(FileName, saveToFolder, True) 'A function to create a unique file name
FileData("FileData").SaveToFile templatePath
SaveTemplateToDisk = templatePath
End Function
It gets called like this:
Dim tempPath As String
Dim fileData as DAO.Field2
Dim folderToSaveTo as string
folderToSaveTo = "C:\some\folder"
set fileData = rsParent.Fields("BackUpAttachments")
tempPath = exporter.SaveTemplateToDisk("Name of file.ext", fileData , folderToSaveTo)
The attachment field is kind of like a recordset withing a field.
So with the help of someone, I changed the line:
Set rsParent = CurrentDB.OpenRecordset("SELECT * FROM tblICTRequested")
To:
Set rsParent = CurrentDB.OpenRecordset("SELECT * FROM tblICTRequested WHERE ID =" & Me.txtRequestedID)
This seems to be working perfectly for my purpose! Thank you to everyone who provided information!

Error initializing PDF reDirect ProFinding to merge two files

I've found this code that should find two matching pdf-filenames and merges them into 1 pdf-file always in the same order. File 1 then File 2.
The code matches filenames based on the first part of the filename, before the AnotherWord 2014.pdf or before SomeWord.pdf.
Example document name1: John Doe SomeWord.pdf
Example document name2: John Doe AnotherWord 2014.pdf
I use PDF reDirect Pro v2.5.2 (freeware) and a reference to the program.
The problem I have is that the line
Dim oPDF As New PDF_reDirect_v25002.Batch_RC_AXD
That gives me the error:
User-defined type not defined
How can I fix this?
This is the whole code:
Private Sub Knop0_Click()
'Only works with PDF reDirect Pro v2.5.2
'And needs to have a reference to PDF_reDirect_v2500 and PDF reDirect Pro Remote Control
Dim fs As Object
Dim fld As Object
Dim fld2 As Object
Dim objFile As Object
Dim objFile2 As Object
Set fs = CreateObject("Scripting.FileSystemObject")
Dim oPDF As New PDF_reDirect_v25002.Batch_RC_AXD
Dim TempBool As Boolean
Dim Files_to_Merge(1) As String
Dim ObjFileName() As String
Dim CellNameValue() As String
Dim ofn As String
Dim cnv As String
Dim i As Integer
Set fld = fs.GetFolder("C:\pdf")
Set fld2 = fs.GetFolder("C:\pdf\merged")
i = 1
For Each objFile In fld.files
For Each objFile2 In fld.files
CellNameValue() = Split(objFile.Name, " SomeWord.pdf")
cnv = CellNameValue(0)
ObjFileName() = Split(objFile2.Name, " AnotherWord 2014.pdf")
ofn = ObjFileName(0)
Files_to_Merge(1) = fld & "\" & ofn & " AnotherWord 2014.pdf"
Files_to_Merge(0) = fld & "\" & cnv & " SomeWord.pdf"
If StrComp(ofn, cnv) = 0 Then
With oPDF
TempBool = .Utility_Merge_PDF_Files(fld2 & "\" & ofn & " AnotherWord 2014.pdf", Files_to_Merge) 'The file merges here unless it generates an error and goes to If Not TempBool Then...
If Not TempBool Then
MsgBox "An Error Occured: etc."
Else
'Optional
End If
End With
End If
i = i + 1
Next objFile2
i = i + 1
Next objFile
Set oPDF = Nothing
End Sub
As I said in my comments this should work assuming your trial Pro version will still allow this feature.
You just have to make sure you're using the correct version of the object that has been registered on your system.
Can you delete the line Dim oPDF As New PDF_reDirect_v25002.Batch_RC_AXD and start retyping it from scratch - not copy/pasting? Does the Object for the tool show up in Intellisense as you start typing PDF_Re
Put in the object that it finds PDF_reDirect_v2500 if that's what it is - then type the . and start typing Batch to fill in the last part. You have to use the current version of the object reference.
Compile your code and see if gets past that line

vbscript error: Name Redifiined; Line 43: ExecuteGlobal sFileContents

Question from a amatuer scripter with informal coding background:
I've researched this on stack, msdn, random scripting websites but can't seem to glean a concrete solution. So please be advised this request for help is a last resort even if the solution is simple.
To put it simply, I'm trying to call a function that parses the last modified date of a file into an array of date formats. The filepath is the function parameter. These files are .vbs files in a client-side testing environment. This will be apparent if you look at the script.
My best guess is the "name redefined" error has something to do global variables being Dim'd in some way that's throwing the error.
Anyway, here's the calling sub:
Option Explicit
'=============================
'===Unprocessed Report========
'=============================
'*****Inputs: File Path*********************
dim strFolderPath, strFilename, strReportName, strFileExt, FullFilePath
strFolderPath = "C:\Users\C37745\Desktop\"
strFilename = "UNPROCESSED_REPORT"
strReportName = "Unprocessed"
strFileExt = ".xlsx"
'************************************
FullFilePath = strFolderPath & strFilename & strFilename & strFileExt
'************************************
Sub Include(MyFile)
Dim objFSO, oFileBeingReadIn ' define Objects
Dim sFileContents ' define Strings
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oFileBeingReadIn = objFSO.OpenTextFile(MyFile, 1)
sFileContents = oFileBeingReadIn.ReadAll
oFileBeingReadIn.Close
ExecuteGlobal sFileContents
End Sub
Include "C:\Users\C37745\Desktop\VBStest\OtherTest\TEST_DLM.vbs"
''''''''''FOR TESTING''''''''''''''
Dim FilePath, varTEST
strFilePath = FullFilePath
varTEST = ParseDLMToArray(strFilePath)
msgbox varTESTtemp(0)
'''''''''''''''''''''''''''''''''
Here's the function I'm trying to call (or read, I guess):
Function ParseDLMtoArray(strFilePath)
Dim strFilePath, dlmDayD, dlmMonthM, dlmYearYY, dlmYearYYYY, DateFormatArray, dateDLM
Dim objFSO, File_Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set File_Object = objFSO.GetFile(strFilePath)
dateDLM = File_object.DateLastModified
dlmDayD = Day(dateDLM)
dlmMonthM = Month(dateDLM)
dlmYearYY = Right(Year(dateDLM),2)
dlmYearYYYY = Year(dateDLM)
'Adds a leading zero if a 1-digit month is detected
If(Len(Month(dlmDayD))=1) Then
dlmmonthMM ="0"& dlmMonthM
Else
dlmMonthMM = dlmMonthM
End If
'Adds a leading zero if a 1-digit day is detected
If(Len(Day(dlmDayD))=1) Then
dlmDayDD = "0" & dlmDayD
Else
dlmDayDD = dlmDayD
End If
varDLM_mmyyyy = dlmMonthMM & dlmYearYYYY
varDLM_mmddyy = dlmMonthMM & dlmDayDD & dlmYearYY
varDLM_mmddyyyy = dlmMonthMM & dlmDayDD & dlmYearYYYY
DateFormatArray = Array( _
varDLM_mmyyyy, _
varDLM_mmddyy, _
varDLM_mmddyyyy _
)
ParseDLMtoArray = DateFormatArray
End Function
Any advice is appreciated, including general feedback on best practices if you see an issue there. Thanks!
Your
Function ParseDLMtoArray(strFilePath)
Dim strFilePath
...
tries to declare/define strFilePath again. That obviously can't be allowed, because it would be impossible to decide whether that variable should contain Empty (because of the Dim) or the argument you passed.
At a first glance at your code, you can just delete the Dim strFilePath.

VBA ActiveDocument Concerns / Alternatives?

I'm using VBA in access to open up a protected word template, fill in the data, and then re-protect it.... this way, if the database system goes down, the word template can still be used manually in its protected state.
I have just started using VBA and in this line:
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
I'm concerned that whilst running the code in access, that if the user opens up another word document and makes it the focus, that it will occidentally get protected instead of the other. How do I keep active focus on the document I'm writing to... or do I need to reference my document somehow using WordApp.protect (or something similar that works)
Private Sub Command0_Click()
Dim WordApp As Word.Application
Dim strDatabasePath As String
Dim strTemplatePath As String
Dim strTemplate As String
Dim strJobTitle As String
Dim strFile As String
strFile1 = "testcoc.dotx"
strFile2 = "testcoc-private.dotx"
strDatabasePath = CurrentProject.Path & "\"
strTemplatePath = "\templates\"
strTemplate = strDatabasePath & strTemplatePath & strFile2
On Error Resume Next
Set WordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set WordApp = CreateObject("Word.Application")
End If
On Error GoTo ErrHandler
WordApp.Visible = True
WordApp.WindowState = wdWindowStateMaximize
WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True
'strJobTitle = DLookup("JobTitle", "Job", "JobNum = " & [JobType])
strJobTitle = DLookup("JobTitle", "Job", "JobNum = 'J0456'")
With WordApp.Selection
'Unprotect the file
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
.Goto what:=wdGoToBookmark, Name:="bm_0_4"
.TypeText strJobTitle
End With
'Reprotect the document.
'If ActiveDocument.ProtectionType = wdNoProtection Then
'ActiveDocument.Protect _
'Type:=wdAllowOnlyFormFields, NoReset:=True, Password:=""
'End If
DoEvents
WordApp.Activate
Set WordApp = Nothing
Exit Sub
ErrHandler:
Set WordApp = Nothing
End Sub
Thank You
I haven't tried this but WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True does return the new document. So I would do something like
Dim doc as Word.Document
Set doc = WordApp.Documents.Add(Template:=strTemplate, NewTemplate:=True)
and reference doc throughout my code instead of ActiveDocument. It seems like doing that should get help you avoid the particular situation you're concerned about.

Moving Files in MSOffice Access 2010

I am attempting to create a button on one of my forms in Access that will move a file from one folder to another. The filepath of the item is stored in the database. My current approach is using VB and is displayed here.
Private Sub Command21_Click()
Dim d As Database
Dim r As Recordset
Dim path As Field
Dim fromPath As String
Dim toPath As String
Set d = CurrentDb()
Set r = d.OpenRecordset("Documents")
Set path = r.Fields("Action Items Location")
While Not r.EOF
fromPath = path
Set toPath = My.Computer.FileSystem.GetParentPath(fromPath) 'Error line
toPath = toPath & "\to folder"
My.Computer.FileSystem.MoveFile fromPath, toPath
Wend
End Sub
I keep getting an error saying object required on the line marked Error line. How do I fix this error, or am I even going about it the correct way?
Thanks for the replies, though after a bit more research, and the suggestion of #Basdwarf, I was able to find a solution. Here's the finished code
Private Sub Command21_Click()
Dim d As Database
Dim r As Recordset
Dim path As Field
Dim fromPath As String
Dim toPath As String
Dim fileName As String
Dim filesystem As Object
Set filesystem = CreateObject("Scripting.FilesystemObject")
Set d = CurrentDb()
Set r = d.OpenRecordset("Documents")
Set path = r.Fields("Action Items Location")
fromPath = path
fileName = filesystem.GetFileName(path)
toPath = filesystem.GetParentFolderName(filesystem.GetParentFolderName(fromPath)) & "\to folder" & "\" & fileName
MsgBox (fromPath)
MsgBox (toPath)
FileCopy fromPath, toPath
Kill fromPath
End Sub
GetParentPath is not an available method in the VBA.Filesystem class in Access.
Go into Code, View, Object Browser, search Filesystem for available methods.
You can use GetFileInfo to find the files directory.