Edit : Sorry i forgot to mention that is VBA for Excel
First time i post on this sub reddit. I would like to something very simple, yet I have no heckin idea how to do it.
Let me give you a bit of context : In my company we have a standard model tool, which uses a standard excel file as input.
When you want to update your inputs from an old template, you download a standard file from a platform, and use a sub that doesn't take any arguments (called "upgrade engine"). Wen you call Upgrade engine, there is a file dialog tab that opens, and helps you select the source file you want to upgrade.
I am in a testing team for the standard model and i have to create a lot of templatse for each new release of the model for non regression testing purpose. So i would like to automatize the process. I cannot , and this is the important detail here, change the code of the standard template.
So i created a kind of masterfile with all my non regression test use cases, their address etc to update them one by one.
Here is my current code:
Public gParamTab As Variant
Public gHypTab As Variant
Public gSourcefolder As String
Public gBlankFolder As String
Public gTgtfolder As String
Public Const gParamTabColUseCase As Byte = 1
Public Const gParamTabColTTtgt As Byte = 2
Public Const gParamTabColTTSource As Byte = 3
Public Const gParamTabColFlagRetrieve As Byte = 4
Public Const gParamTabColTTCase As Byte = 5
Public Const gParamTabColFlagUpgrade As Byte = 6
Public Const gBlankTTName As String = "Table_Template_MVP_case"
Public Const gExtension As String = ".xlsb"
Sub init()
gParamTab = Sheets("Parameters").Range("gParamTab")
gHypTab = Sheets("NDD HYP").Range("gHypTab")
gSourcefolder = Sheets("Parameters").Range("gSourcefolder")
gTgtfolder = Sheets("Parameters").Range("gTgtfolder")
gBlankFolder = Sheets("Parameters").Range("gBlankFolder")
End Sub
Sub updateTT()
Call init
Dim lFullname_blank As String, lFullname_source As String, lFullname_tgt As String
Dim lGlobalrange As Variant
Dim lGlobaltable() As Variant
Dim lBlankTT As Workbook
Dim lLastRow As Long
Dim lSearchedVariable As Variant
Dim lBlankTTupgradeengine As String
lcol = 2
For lUsecase = 2 To UBound(gParamTab, 1)
If gParamTab(lUsecase, gParamTabColFlagUpgrade) = 1 Then
lFullname_blank = gBlankFolder & "\" & gBlankTTName & gParamTab(lUsecase, gParamTabColTTCase) & gExtension
lFullname_source = gSourcefolder & "\" & gParamTab(lUsecase, gParamTabColTTSource) & gExtension
lFullname_tgt = gTgtfolder & "\" & gParamTab(lUsecase, gParamTabColTTtgt) & gExtension
Set lBlankTT = Workbooks.Open(lFullname_blank)
lBlankTTupgradeengine = gBlankTTName & gParamTab(lUsecase, gParamTabColTTCase) & gExtension & "!UpgradeEngine.UpgradeEngine"
Application.Run lBlankTTupgradeengine
End If
Next
End Sub
So i come the main issue, how can I, from another macro, after the statement "Application.Run lBlankTTupgradeengine" , the upgrade engine macro starts, and calls the following function embedded in the "BlankTT" :
Sub UpgradeEngine()
Set wkb_target = ThisWorkbook
Set wkb_source = macros_Fn.Open_wkb()
[...]
Function Open_wkb() As Workbook
Dim fileName As Variant
With Application.FileDialog(msoFileDialogFilePicker)
' Makes sure the user can select only one file
.AllowMultiSelect = False
' Filter to just keep the relevants types of files
.filters.Add "Excel Files", "*.xlsm; *.xlsb", 1
.Show
' Extact path
If .SelectedItems.Count > 0 Then
fileName = .SelectedItems.Item(1)
Else
End
End If
End With
If (fileName <> False) Then
Set Open_wkb = Workbooks.Open(fileName:=fileName, IgnoreReadOnlyRecommended:=False, Editable:=False, ReadOnly:=True, UpdateLinks:=False)
Else
MsgBox "This file is already open. Please close it before launching the function."
End
End If
End Function
This function opens as I said before, a dialog box with a brows button to select the excel spreadsheet to use as ssource.
My question is, how can i fill automatically this Filedialog from my code, without changing the code of the standard excel file?
Thanks a lot for your help!
I tried to search everywhere but i did not find anything about this situation.
I'm trying to move a copy of the upgrade engine, but with an argument in the sub instead of the filedialog but the macro is too complex ..
Your best bet would be to add an optional parameter to UpgradeEngine - something like:
Sub UpgradeEngine(Optional wbPath as String = "")
'...
Set wkb_target = ThisWorkbook
If Len(wbPath) > 0 Then
Set wkb_source = Workbooks.Open(wbPath) 'open using provided file path
Else
Set wkb_source = macros_Fn.Open_wkb() 'open user-selected file
End If
'...
'...
Then you can call it and pass in the path you want.
FYI the code in Open_wkb seems off (at least, the "already open" message seems wrong). fileName <> False only checks if the user made a selection: it doesn't indicate anything about whether a selected file is already open or not.
Related
Trying to use Excel VBA to capture all the file attributes from files on disk, including extended attributes. Was able to get it to loop through the files and capture the basic attributes (that come from the file system):
File Path
File Name
File Size
Date Created
Date Last Accessed
Date Last Modified
File Type
Would also like to capture the extended properties that come from the file itself:
Author
Keywords
Comments
Last Author
Category
Subject
And other properties which are visible when right clicking on the file.
The goal is to create a detailed list of all the files on a file server.
You say loop .. so if you want to do this for a dir instead of the current document;
Dim sFile As Variant
Dim oShell: Set oShell = CreateObject("Shell.Application")
Dim oDir: Set oDir = oShell.Namespace("c:\foo")
For Each sFile In oDir.Items
Debug.Print oDir.GetDetailsOf(sFile, XXX)
Next
Where XXX is an attribute column index, 9 for Author for example.
To list available indexes for your reference you can replace the for loop with;
for i = 0 To 40
debug.? i, oDir.GetDetailsOf(oDir.Items, i)
Next
Quickly for a single file/attribute:
Const PROP_COMPUTER As Long = 56
With CreateObject("Shell.Application").Namespace("C:\HOSTDIRECTORY")
MsgBox .GetDetailsOf(.Items.Item("FILE.NAME"), PROP_COMPUTER)
End With
You can get this with .BuiltInDocmementProperties.
For example:
Public Sub PrintDocumentProperties()
Dim oApp As New Excel.Application
Dim oWB As Workbook
Set oWB = ActiveWorkbook
Dim title As String
title = oWB.BuiltinDocumentProperties("Title")
Dim lastauthor As String
lastauthor = oWB.BuiltinDocumentProperties("Last Author")
Debug.Print title
Debug.Print lastauthor
End Sub
See this page for all the fields you can access with this: http://msdn.microsoft.com/en-us/library/bb220896.aspx
If you're trying to do this outside of the client (i.e. with Excel closed and running code from, say, a .NET program), you need to use DSOFile.dll.
'vb.net
'Extended file stributes
'visual basic .net sample
Dim sFile As Object
Dim oShell = CreateObject("Shell.Application")
Dim oDir = oShell.Namespace("c:\temp")
For i = 0 To 34
TextBox1.Text = TextBox1.Text & oDir.GetDetailsOf(oDir, i) & vbCrLf
For Each sFile In oDir.Items
TextBox1.Text = TextBox1.Text & oDir.GetDetailsOf(sFile, i) & vbCrLf
Next
TextBox1.Text = TextBox1.Text & vbCrLf
Next
I was finally able to get this to work for my needs.
The old voted up code does not run on windows 10 system (at least not mine). The referenced MS library link below provides current examples on how to make this work. My example uses them with late bindings.
https://learn.microsoft.com/en-us/windows/win32/shell/folder-getdetailsof.
The attribute codes were different on my computer and like someone mentioned above most return blank values even if they are not. I used a for loop to cycle through all of them and found out that Title and Subject can still be accessed which is more then enough for my purposes.
Private Sub MySubNamek()
Dim objShell As Object 'Shell
Dim objFolder As Object 'Folder
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace("E:\MyFolder")
If (Not objFolder Is Nothing) Then
Dim objFolderItem As Object 'FolderItem
Set objFolderItem = objFolder.ParseName("Myfilename.txt")
For i = 0 To 288
szItem = objFolder.GetDetailsOf(objFolderItem, i)
Debug.Print i & " - " & szItem
Next
Set objFolderItem = Nothing
End If
Set objFolder = Nothing
Set objShell = Nothing
End Sub
Lucky discovery
if objFolderItem is Nothing when you call
objFolder.GetDetailsOf(objFolderItem, i)
the string returned is the name of the property, rather than its (undefined) value
e.g. when i=3 it returns "Date modified"
Doing it for all 288 values of I makes it clear why most cause it to return blank for most filetypes
e.g i=175 is "Horizontal resolution"
I'm trying to write a VBA macro that will read through a text document and place specific words into columns. UPDATE: Here's a sample of the file, apparently it's XML, so at least I learned something new today. So i guess what I need is a program to shed the XML parts, and place just the text into columns.
<Alarm>
<ID>1002</ID>
<Type>Fault</Type>
<Message>Bad Brake</Message>
<Tagname>error.e2</Tagname>
</Alarm>
<Alarm>
<ID>1004</ID>
<Type>Fault</Type>
<Message>No Motion</Message>
<Tagname>error.e4</Tagname>
</Alarm>
<Alarm>
<ID>1005</ID>
<Type>Fault</Type>
<Message>Upper safety door open</Message>
<Tagname>error.e5</Tagname>
</Alarm>
Ultimately, I'm trying to put the 4 digit error codes in column A (i.e. 1002, 1004...), and the error message in column B (i.e. Bad Brake, No motion....). I'll paste what I have so far, I tried coding it for just one pair of data to start. I'm stuck trying to get the error message into column B. The error messages all start in the same position on each line, but I can't figure out how to stop copying the text, since each error message is a different length of characters. Any ideas?
(P.S. - I apologize if the code is terrible, I've been interning as an electrical engineer, so my programming has gotten rather rusty.)
Private Sub CommandButton1_Click()
Dim myFile As String, textLine As String, ID As Integer, error_msg As Integer
myFile = "C:\Users\scholtmn\Documents\Projects\Borg_Warner_txt_file\BW_fault_codes.txt"
Open myFile For Input As #1
Do Until EOF(1)
Line Input #1, textLine
Text = Text & textLine
Loop
Close #1
ID = InStr(Text, "<ID>")
error_msg = InStr(Text, "<Message>")
Range("A1").Value = Mid(Text, ID + 4, 4)
Range("B1").Value = Mid(Text, error_msg + 9, (InStr(Text, " <") - 31))
End Sub
Please, try the next code:
Sub ExtractErrorsDefinition()
'it needs a reference to 'Microsoft XML, v6.0'
Dim XMLFileName As String, oXMLFile As New MSXML2.DOMDocument60, sh As Worksheet
Dim N As MSXML2.IXMLDOMNode, i As Long, arr
Set sh = ActiveSheet 'use here the necessary sheet
XMLFileName = "the full text file path" '"C:\Utile\Teste Corel\XMLtext.txt"
oXMLFile.Load (XMLFileName)
ReDim arr(1 To oXMLFile.SelectNodes("AlarmDictionary/Alarm").length, 1 To 2): i = 1
For Each N In oXMLFile.SelectNodes("AlarmDictionary/Alarm")
arr(i, 1) = N.SelectSingleNode("ID").Text: arr(i, 1) = N.SelectSingleNode("Message").Text: i = i + 1
Next
sh.Range("A2").Resize(UBound(arr), 2).value = arr
End Sub
It may work using late binding, but it is better to have the intellisense suggestion, especially when not very well skilled in working with XML.
If looks complicated to add such a reference, I can add a piece of code to automatically add it.
Please, run the next code to automatically add the necessary reference. Save your workbook and run the first code after:
Sub addXMLRef()
'Add a reference to 'Microsoft Scripting Runtime':
'In case of error ('Programmatic access to Visual Basic Project not trusted'):
'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
' check "Trust access to the VBA project object model"
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\System32\msxml6.dll"
End Sub
It looks like the txt file you are using is actually an xml file. If you changed the format, this piece of code I slightly adjusted from here should work fine.
Sub From_XML_To_XL()
Dim xmlWb As Workbook, xSWb As Workbook, xStrPath$, xfdial As FileDialog, _
xFile$, lr%, first As Boolean, r As Range
first = True
Set xfdial = Application.FileDialog(msoFileDialogFilePicker)
xfdial.AllowMultiSelect = False
xfdial.Title = "Select an XML File"
If xfdial.Show = -1 Then xStrPath = xfdial.SelectedItems(1) & ""
If xStrPath = "" Then Exit Sub
Set xSWb = ThisWorkbook
lr = xSWb.ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row ' last used row, column A
xFile = xStrPath
Set xmlWb = Workbooks.OpenXML(xFile)
If first Then
Set r = xmlWb.Sheets(1).UsedRange ' with header
Else
xmlWb.Sheets(1).Activate
Set r = ActiveSheet.UsedRange
Set r = Range(Cells(3, 1), Cells(r.Rows.Count, r.Columns.Count))
End If
r.Copy xSWb.ActiveSheet.Cells(lr + 1, 1)
lr = xSWb.ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row
xmlWb.Close False
first = False
End Sub
I think you'll find this task a lot easier if you take advantage of the fact it is in XML format. You can find more information about working with XML in VBA here.
As Ben Mega already stated: you have an XML-File - why not use XML-functionality.
Add "Microsoft XML, v6.0" to your project references - then you can use this code
Public Sub insertTextFromXML()
Dim objXML As MSXML2.DOMDocument60
Set objXML = New MSXML2.DOMDocument60
If Not objXML.Load("T:\Stackoverflow\Test.xml") Then
Err.Raise objXML.parseError.ErrorCode, , objXML.parseError.reason
End If
Dim nAlarm As MSXML2.IXMLDOMNode
'loop through all alarms and output ID plus message
For Each nAlarm In objXML.SelectNodes("AlarmDictionary/Alarm")
With nAlarm
Debug.Print .SelectSingleNode("ID").Text, .SelectSingleNode("Message").Text
End With
Next
'Filter for ID 1004
Set nAlarm = objXML.SelectSingleNode("AlarmDictionary/Alarm[ID=1004]")
Debug.Print nAlarm.XML
End Sub
You can google for VBA XPath to find out how to access the various values.
Dears:
i have an issue with below code
as i need to Merge Two Files once importing them by filedialog then copy the result direclty to another workbook
the below cope is working but suddnly it copies only data of the first file which its file size is the bigger and i do not know why
Sub IIII_Import_BSS_Stock_All_Files()
Dim ws As Worksheet
Dim wb As Workbook
Dim Imported1wb As Workbook
Dim Imported1ws As Worksheet
Dim DialFirstFile As FileDialog
Dim Imported1FileName As String
Dim Imported1LastRow As Long
Dim Imported2wb As Workbook
Dim Imported2ws As Worksheet
Dim DialSecondFile As FileDialog
Dim Imported2FileName As String
Dim Imported2LastRow As Long
'FileName after using File Len for ordering the first file to be (available) and the second one to be (Maintain)
Dim FileLenNameSize1 As Long
Dim FileLenNameSize2 As Long
Dim TempFileOrder As String
Dim UpperArray() As String
Dim LowerArray() As String
Dim split_len As Long
Dim Imported1FileNameLnSpFn As String
Dim Imported2FileNameLnSpFn As String
Dim DestinationRange As Range
Dim ImportSelectARange As Range
Dim ImportSelectBRange As Range
Const SelectCols As String = "D:D,A:A,C:C,H:H,K:K,I:I"
Application.ScreenUpdating = False
Set DialFirstFile = Application.FileDialog(msoFileDialogFilePicker)
DialFirstFile.AllowMultiSelect = False
DialFirstFile.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
DialFirstFile.Show
Imported1FileName = DialFirstFile.SelectedItems.Item(1)
need.
If InStr(Imported1FileName, ".xls") = 0 Then
Exit Sub
End If
Set Imported1wb = Workbooks.Open(Imported1FileName)
Application.ScreenUpdating = False
Set DialSecondFile = Application.FileDialog(msoFileDialogFilePicker)
DialSecondFile.AllowMultiSelect = False
DialSecondFile.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
DialSecondFile.Show
Imported2FileName = DialSecondFile.SelectedItems.Item(1)
If InStr(Imported2FileName, ".xls") = 0 Then
Exit Sub
End If
Set Imported2wb = Workbooks.Open(Imported2FileName)
Set ws = ActiveSheet
FileLenNameSize1 = FileLen(Imported1FileName)
FileLenNameSize2 = FileLen(Imported2FileName)
If (FileLenNameSize1 < FileLenNameSize2) Then
TempFileOrder = Imported1FileName
Imported1FileName = Imported2FileName
Imported2FileName = TempFileOrder
End If
UpperArray = Split(Imported1FileName, "\")
LowerArray = Split(Imported2FileName, "\")
split_len = UBound(UpperArray) - LBound(UpperArray)
Imported1FileNameLnSpFn = UpperArray(split_len)
Imported2FileNameLnSpFn = LowerArray(split_len)
Set Imported1ws = Workbooks(Imported1FileNameLnSpFn).Worksheets("Default")
Set Imported2ws = Workbooks(Imported2FileNameLnSpFn).Worksheets("Default")
Imported1LastRow = Imported1ws.Cells(Imported1ws.Rows.Count, "A").End(xlUp).Offset(1).Row
Imported2LastRow = Imported2ws.Cells(Imported2ws.Rows.Count, "A").End(xlUp).Row
'Copy & Paste to the total stock sheet from the merged file
' but only Copy Selection of Non Adjacent Columns of the imported file not copying the entire sheet
Set Imported1ws = Workbooks(Imported1FileNameLnSpFn).Worksheets("Default")
'Selection of data in sheet 2 to be copied
Set ImportSelectARange = Intersect(Imported1ws.Range(SelectCols), Imported1ws.Rows("2:" & Imported1LastRow))
Set ImportSelectBRange = Intersect(Imported2ws.Range(SelectCols), Imported2ws.Rows("2:" & Imported2LastRow))
'Selection of last empy row at Sheet 1 to be copy data into it
'Copy from sheet 2 to sheet 1
Set Destination2FRange = ThisWorkbook.Worksheets("Total Stock").Range("A2")
Set Imported1ws = Workbooks(Imported1FileNameLnSpFn).Worksheets("Default")
Imported2ws.Range("A2:L" & Imported2LastRow).Copy Destination:=Imported1ws.Cells(Imported1LastRow + 1, "A")
'Copy from sheet 1 to sheet 2
Set Imported1ws = Workbooks(Imported1FileNameLnSpFn).Worksheets("Default")
Imported2ws.Range("A2:L" & Imported2LastRow).Copy Destination:=Imported1ws.Cells(Imported1LastRow + 1, "A")
ImportSelectARange.Copy _
Destination:=Destination2FRange
Workbooks(Imported1FileNameLnSpFn).Close
Workbooks(Imported2FileNameLnSpFn).Close
Please look at this part of your code.
UpperArray = Split(Imported1FileName, "\")
LowerArray = Split(Imported2FileName, "\")
split_len = UBound(UpperArray) - LBound(UpperArray)
Imported1FileNameLnSpFn = UpperArray(split_len)
Imported2FileNameLnSpFn = LowerArray(split_len)
The first 2 lines create 2 arrays. They would have the same number of elements if the two files were taken from the same directory, like "C:\User\MyFile.xls". But if one of the files is from a sub-directory it would have more elements, like "C:\User\MyFolder\MyFile.xls". The third line of code examines this difference and assigns it to the variable split_len. We therefore know that split_len may contain 0, a positive or negative low number.
In the next 2 lines this number is used to define an element of the arrays first created. The chance that this will be a file name are remote because the file name is in the last element of each array. This code would extract it.
Imported1FileNameLnSpFn = UpperArray(UBound(UpperArray))
Imported2FileNameLnSpFn = LowerArray(UBound(LowerArray))
The variable split_Len is ill-conceived and not useful as an array index. It can only be sheer coincidence that it does work on occasion. On principle, you may improve your code if you don't handle the two files parallel. Instead, develop a sub routine that handles one file at a time, call it twice with different files name or file objects as argument after determining which file to handle first.
I'm not sure that abandoning FileDialog is a good idea. In fact, if your two workbooks are in the same file location you could open them in one go by allowing multiple selection in the file open dialog box. In the code below the presumption is that the files are in different folders. Therefore I made a loop to call a function that returns one workbook at a time.
Option Explicit
Sub MergeFiles()
' 174
Dim Src(2) As Workbook ' sources
Dim Title As String
Dim FolderPath As String
Dim f As Integer ' Loop counter
' set the arguments for the first loop
Title = "Choose the first workbook to open"
' FolderPath can be a full file name (path & file name)
' or it can be just a folder name, ending on backslash
FolderPath = "D:\PVT Archive\Class 1\1-2021 (Jan 2023)\"
For f = 1 To 2
Set Src(f) = FileToOpen(Title, FolderPath)
If Src(f) Is Nothing Then Exit Sub ' user made no selection
' now set the arguments for the second loop
Title = "Choose the second workbook to open"
FolderPath = Environ("UserProfile") & "\Desktop\"
Next f
Debug.Print Src(1).Name
Debug.Print Src(2).Name
End Sub
Private Function FileToOpen(MyTitle As String, _
StartAt As String) As Workbook
' 174
' https://www.wallstreetmojo.com/vba-filedialog/
With Application.FileDialog(msoFileDialogOpen)
.Filters.Clear
.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
.Title = MyTitle
.AllowMultiSelect = False
.InitialFileName = StartAt
If .Show = -1 Then Set FileToOpen = Workbooks.Open(.SelectedItems(1))
End With
End Function
At the end of this code you have your two files. Comparing their size is not so easy. You probably need to find a function on the internet. Better use the InitialFileName in the above code to open the bigger file first, or find a way to differentiate them by their content.
I couldn't figure out from your code (I think I see only a part of it) what you want to do with the two files but whatever it is it starts where my above code ends and it would clearly exceed the scope of this thread. The above code puts your logic on a slightly different path but you can try to append your previous code to it and then ask a new question if you need more help.
I am designing a VBA Form in Excel. The Workbook has a table called "images", and inside there I am dropping some images from my local hard drive.
These Workbook & UserForm are to be shared with my colleagues. They might not have these images in their harddrive, but they will have them inside of the Excel table.
I am looking for a way to load an image that's inside of a table inside of an "Image" VBA form control.
In Google all I find is how to load an image from my hard drive (i.e. using an absolute path like "C:/my_images/car.png"). What I can't find is how to load an image that's within a table, i.e. already bundled within the Workbook.
Any ideas?
If you are still interested in this question, I came up with a solution.
First you need to export the picture from the shape into a file. I found that only .jpg files can be used. My code generates a temporary filename (you need to be able to read/write that path but I think it is usually not a problem), and saves the picture by inserting it into a ChartObject, which can export its contents as a picture. I suppose this process may modify (e.g. compress) the original data but I saw no visible difference on the screen.
When this is done, it loads the picture from this file into the Image control on the UserForm.
Finally, it deletes the temporary file to clean up this side-effect.
Option Explicit
' Include: Tools > References > Microsoft Scripting Runtime
Private Sub cmdLoad_Click()
' Assumption: The UserForm on which you want to load the picture has a CommandButton, cmdLoad, and this function is its event handler
Dim imgImageOnForm As Image: Set imgImageOnForm = imgTarget ' TODO: Set which Control you want the Picture loaded into. You can find the Name in the VBA Form Editor's Properties Bar
Dim strSheetName As String: strSheetName = "TargetSheet" ' TODO: Specify the Name of the Worksheet where your Shape (picture) is
Dim strShapeName As String: strShapeName = "TargetPicture" ' TODO: Specify the Name of your Shape (picture) on the Worksheet
Dim strTemporaryFile As String: strTemporaryFile = GetTemporaryJpgFileName ' TODO: Give a path for the temporary file, the file extension is important, e.g. .jpg can be loaded into Form Controls, while .png cannot
LoadShapePictureToFormControl _
strSheetName, _
strShapeName, _
imgImageOnForm, _
strTemporaryFile
End Sub
Private Sub LoadShapePictureToFormControl(strSheetName As String, strShapeName As String, imgDst As MSForms.Image, strTemporaryFile As String)
' Note: This Sub overwrites the contents of the Clipboard
' Note: This Sub creates and deletes a temporary File, therefore it needs access rights to do so
Dim shpSrc As Shape: Set shpSrc = ThisWorkbook.Worksheets(strSheetName).Shapes(strShapeName)
Dim strTmp As String: strTmp = strTemporaryFile
ExportShapeToPictureFile shpSrc, strTmp
ImportPictureFileToImage strTmp, imgDst
FileSystem.Kill strTmp
End Sub
Private Sub ExportShapeToPictureFile(shpSrc As Shape, strDst As String)
shpSrc.CopyPicture xlScreen, xlBitmap
Dim chtTemp As ChartObject: Set chtTemp = shpSrc.Parent.ChartObjects.Add(0, 0, shpSrc.Width, shpSrc.Height)
With chtTemp
.Activate
.Parent.Shapes(.Name).Fill.Visible = msoFalse
.Parent.Shapes(.Name).Line.Visible = msoFalse
.Chart.Paste
.Chart.Export strDst
.Delete
End With
End Sub
Private Sub ImportPictureFileToImage(strSrc As String, imgDst As MSForms.Image)
Dim ipdLoaded As IPictureDisp: Set ipdLoaded = StdFunctions.LoadPicture(strSrc)
Set imgDst.Picture = ipdLoaded
End Sub
Private Function GetTemporaryJpgFileName() As String
Dim strTemporary As String: strTemporary = GetTemporaryFileName
Dim lngDot As Long: lngDot = InStrRev(strTemporary, ".")
If 0 < lngDot Then
strTemporary = Left(strTemporary, lngDot - 1)
End If
strTemporary = strTemporary & ".jpg"
GetTemporaryJpgFileName = strTemporary
End Function
Private Function GetTemporaryFileName() As String
Dim fsoTemporary As FileSystemObject: Set fsoTemporary = New FileSystemObject
Dim strResult As String: strResult = fsoTemporary.GetSpecialFolder(TemporaryFolder)
strResult = strResult & "\" & fsoTemporary.GetTempName
GetTemporaryFileName = strResult
End Function
new and would like to ask if someone could possibly check my code to see where i'm making a mistake.
first, i've created a form with two textboxes and two buttons that will go and get two different directories and the associated files. this is done through a call to a function that loads the dir to the textboxes.
a button to call a function to navigate dir and get the file
Private Sub CommandButton3_Click()
'call selectFile function to select file
selectFile
End Sub
function to get workbooks into textboxes 1 and 2:
Public Function selectFile()
Dim fileNamePath1 As String
Dim fileNamePath2 As String
Dim workbookFilePath1 As String
Dim workbookFilePath2 As String
On Error GoTo exit_
If workbookFilePath1 = Empty And workbookFilePath2 = Empty Then
fileNamePath1 = Application.GetOpenFilename(FileFilter:="Excel Files (*.xls), *.xls", Title:="Open Workbook 1", MultiSelect:=False)
workbookFilePath1 = Dir(fileNamePath1)
'TextBox1.Text = workbookFilePath1
TextBox1.Value = fileNamePath1
fileNamePath2 = Application.GetOpenFilename(FileFilter:="Excel Files (*.xls), *.xls", Title:="Open Workbook 2", MultiSelect:=False)
workbookFilePath2 = Dir(fileNamePath2)
TextBox2.Value = fileNamePath2
If fileNamePath1 = False Or fileNamePath2 = False Then
MsgBox ("File selection was canceled.")
Exit Function
End If
End If
exit_:
End Function
up to here, the code is ok... can do better, but
here's where problems occur... i'd like to pass the directories as objects into the module to diff
button that executes module to diff:
Private Sub CommandButton1_Click()
getTheWorkbooksToCompare(fileNamePath1, fileNamePath2)
End Sub
i know that i've changed myPath1 and myPath2 to Workbooks, where I've had them as strings before
diffing module
Public Sub gettheWorkbooksToCompare(myPath1 As Workbook, myPath2 As Workbook)
Dim myExcelObj
Dim WorkbookObj1
Dim WorkbookObj2
Dim WorksheetObj1
Dim WorksheetObj2
Dim file1 As String
Dim file2 As String
Dim myWorksheetCounter As Integer
Dim i As Worksheet
Set myExcelObj = CreateObject("Excel.Application")
myExcelObj.Visible = True
Set file1 = Dir(myPath1)
Set file2 = Dir(myPath2)
Set WorkbookObj1 = myExcelObj.Workbooks.Open(file1)
Set WorkbookObj2 = myExcelObj.Workbooks.Open(file2)
Set NewWorkbook = myExcelObj.Workbooks.Add
While WorkbookObj1 <> Null And WorkbookObj2 <> Null
'While WorkbookObj1.ActiveWorkbook.Worksheets.count = WorkbookOjb2.ActiveWorkbook.Worksheets.count
myWorksheetCounter = ActiveWorkbook.Worksheets.count
myWorksheetCount = ActiveWorkbook.Worksheets.count
If WorksheetObj1.Worksheets.myWorksheetCounter = WorkbookObj2.Worksheets.myWorksheetCounter Then
Set WorksheetObj1 = WorkbookObj1.Worksheets(myWorksheetCounter)
Set WorksheetObj2 = WorkbookObj2.Worksheets(myWorksheetCounter)
Set myNewWorksheetObj = NewWorkbook.Worksheets(myWorksheetCounter)
For myWorksheetCounter = i To WorksheetObj1
For myWorksheetCount = j To WorksheetOjb2
'If cell.Value myWorksheetObj2.Range(cell.Address).Value Then
If cell.Value = myWorksheetObj2.Range(cell.address).Value Then
myNewWorksheetObj.Range(cell.address).Value = cell.address.Value
myNewWorksheetObj.Range(cell.address).Interior.ColorIndex = 3
Else
cell.Interior.ColorIndex = 0
End If
Next
'if doesn't work... use SaveChanges = True
myNewWorksheetObj.Workbooks.Save() = True
Next
Else
MsgBox ("The worksheets are not the same worksheets." & vbNewLine & "Please try again.")
End If
Wend
Set myExcelObj = Nothing
End Sub
So my question is... can someone please assist in seeing where i'm going wrong? essentially, i'm having some issues in trying to get this working.
much appreciated
i've gone through and cleaned up some areas a little bit... but now have a: "run time error '438': object doesn't support this propety or method" at the while loop code that i've updated the post with
I see a typo on CommandButton1_Click
Private Sub CommandButton1_Click()
getTheWorkbooksToCompare(fileNamePath1, fileNamePath2)
End Sub
Public Sub gettheWorkbooksToCompare(myPath1 As Workbook, myPath2 As Workbook)
There might be something more, but your not capitalizing the "T" in getThe, but you call it that way.