我们能否将多个图像附加到 VBA 中的一个 useform,保存在具有特定命名约定的文件夹中,稍后使用该名称检索?

Can we attach multiple images to a useform in VBA, save in a folder with a specific naming convention and retrieve later using that name?

我有一个 VBA 项目,我需要在其中创建一个用户表单,在该用户表单上应该有一个 select 多个图像的附件按钮,并将它们保存在具有特定名称的文件夹中。稍后,如果有人从搜索框中查找该名称,它应该调用与图像一起保存的所有信息。名称应如下所示 Sh-0001-01(其中 0001 表示发票编号,01 表示附件编号)。

我从另一个论坛得到了一个文件,它可以将图像加载到图像框中并滚动浏览它们,但是除了将新图像复制到后端文件夹之外,没有添加新图像的机制。而且,没有使用特定名称保存附件并使用该名称查找附件的功能。

结果以图片形式附上。可以通过此 link 访问示例代码文件: https://drive.google.com/file/d/1HXLjDIpjNmgxLxegYiexxEykh4f_54sY/view?usp=sharing

由于 Whosebug 强制包含示例代码,以下是驱动器文件中的部分代码:

Public Const fPath As String = "C:\Test\"
Sub LaunchForm()
UserForm1.Show
End Sub

Function PhotoNum(numx As Integer) As String
Dim PhotoNames As String, iFile As String
Dim i As Integer
Dim ArrayPhoto() As Variant
iFile = "*.*"
PhotoNames = Dir(fPath & iFile) 
i = 0
Do Until PhotoNames = ""
i = i + 1
ReDim Preserve ArrayPhoto(1 To i)
ArrayPhoto(i) = PhotoNames
PhotoNames = Dir
Loop
PhotoNum = ArrayPhoto(numx)

End Function

Function MaxPhoto() As Integer
Dim PhotoNames As String, iFile As String
Dim i As Integer
Dim ArrayPhoto() As Variant 
iFile = "*.*"
PhotoNames = Dir(fPath & iFile)
i = 0
Do Until PhotoNames = ""
i = i + 1
ReDim Preserve ArrayPhoto(1 To i)
ArrayPhoto(i) = PhotoNames
PhotoNames = Dir
Loop

MaxPhoto = UBound(ArrayPhoto)

End Function

感谢任何帮助。

请尝试下一种方法。必须存在名为“tbOrder”的文本框。其中必须输入 order/invoice 数字(手动或通过代码)。其余控件是您发送的测试工作簿中使用的控件。请复制表单代码模块中的下一个代码。标准模块中只应存在显示表单的子项。添加了用于添加附件的新按钮 (btAttach) 和用于指定多选选项的复选框 (chkManyAtt):

Option Explicit

Private Const fPath As String = "C:\test\"
Private photoNo As Long, arrPhoto() As Variant, boolNoEvents As Boolean, prevVal As Long, boolFound As Boolean
Private boolManyAttch As Boolean

Private Sub btAttach_Click()
    If Len(tbOrder.Text) <> 7 Then MsgBox "An invoice number is mandatory in its specific text box (7 digits long)": Exit Sub
    Dim noPhotos As Long, runFunc As String
    
    runFunc = bringPicture(Left(tbOrder.Text, 7), True)
    If Not boolFound Then noPhotos = -1
    
    Dim sourceFile As String, destFile As String, attName As String, strExt As String, i As Long
    
    With Application.FileDialog(msoFileDialogFilePicker)
        .Title = "Please, select the picture to be added as attachment for invoice " & Me.tbOrder.Text & " (" & photoNo & ")"
        .AllowMultiSelect = IIf(boolManyAttch = True, True, False)
        .Filters.Add "Picture Files", "*.jpg", 1
        If .Show = -1 Then
                For i = 1 To .SelectedItems.Count
                    sourceFile = .SelectedItems(i): 'Stop
                    attName = Me.tbOrder.Text & "-" & Format(IIf(noPhotos = -1, 1, photoNo + 1), "00")
                    strExt = "." & Split(sourceFile, ".")(UBound(Split(sourceFile, ".")))
                    destFile = fPath & attName & strExt
                    FileCopy sourceFile, destFile
                    ReDim Preserve arrPhoto(IIf(noPhotos = -1, 0, UBound(arrPhoto) + 1)): noPhotos = 0
                    arrPhoto(UBound(arrPhoto)) = attName & strExt
                    photoNo = photoNo + 1
                Next i
        Else
            Exit Sub
        End If
    End With
    Me.TextBox2.Text = photoNo: Me.TextBox2.Enabled = False
    Me.TextBox1.Text = photoNo
End Sub

Private Sub chkManyAtt_Click()
    If Me.chkManyAtt.Value Then
        boolManyAttch = True
    Else
        boolManyAttch = False
    End If
End Sub

Private Sub CommandButton1_Click() 'Prev button
 Dim currPic As Long

 currPic = Me.TextBox1.Value

 If currPic > 1 Then
    Me.Image1.Picture = LoadPicture(fPath & arrPhoto(currPic - 2))
    boolNoEvents = True                'stop the events when TextBox1 is changed
     Me.TextBox1.Text = currPic - 1
     prevVal = Me.TextBox1.Value
    boolNoEvents = False              'restart events
 End If
End Sub
Private Sub CommandButton2_Click() 'Next button
 Dim currPic As Long

    currPic = Me.TextBox1.Value

 If currPic < photoNo Then
    Me.Image1.Picture = LoadPicture(fPath & arrPhoto(currPic))
    boolNoEvents = True
      Me.TextBox1.Text = currPic + 1
      prevVal = Me.TextBox1.Value
    boolNoEvents = False
  Else
    MsgBox "Please, select a valid image number..."
 End If
End Sub

Private Sub tbOrder_Change() 'the textbox where to input the order/invoice nubmer
    Dim firstPict As String
    If Len(tbOrder.Text) >= 7 Then
       photoNo = 0: Erase arrPhoto   'clear the variable keeping the number of found photos and the array keeping them
       firstPict = bringPicture(Left(tbOrder.Text, 7)) 'to make it working even if you paste "Sh-0002-20"
       If firstPict <> "" Then 'determining the first picture to be placed
            With Me.Image1
                .Picture = LoadPicture(fPath & firstPict)
                .PictureSizeMode = fmPictureSizeModeZoom
            End With
            boolNoEvents = True      'avoiding the event to be triggeret twice
                Me.TextBox1.Text = 1
                
                With Me.TextBox2
                    .Enabled = True
                    .Text = photoNo
                    .Enabled = False
                End With
            boolNoEvents = False
        Else
            Me.Image1.Picture = LoadPicture(vbNullString) 'clear the picture if no order/invoice have been written in the text box
            Me.TextBox2.Text = "": Me.TextBox1.Text = ""
       End If
    End If
End Sub

Function bringPicture(strName As String, Optional boolAttach As Boolean = False) As String
   Dim PhotoNames As String, arrPh, noPict As Long, firstPict As String, ph As Long
   PhotoNames = Dir(fPath & strName & "*.*") 'find the first photo with the necessary pattern name

   If boolAttach Then
        ReDim arrPhoto(0): photoNo = 0
   Else
        ReDim arrPhoto(photoNo)   'firstly ReDim the array
   End If
   boolFound = False
   Do While PhotoNames <> ""
        boolFound = True
        arrPhoto(photoNo) = PhotoNames: photoNo = photoNo + 1
        ReDim Preserve arrPhoto(photoNo)
        PhotoNames = Dir()
   Loop
   If photoNo > 0 Then
        ReDim Preserve arrPhoto(photoNo - 1) 'eliminate the last empty array element
        bringPicture = arrPhoto(0)                 'return the first photo in the array
  End If
  
End Function

Private Sub TextBox1_Change()                     'manually change the picture number
    If Not boolNoEvents Then                        'to not be treggered when changed by code
        If IsNumeric(Me.TextBox1.Value) Then   'to allow only numbers
            If Len(Me.TextBox1.Value) >= Len(CStr(photoNo)) Then 'to allow numbers less or equal with the maximum available
                If CLng(TextBox1.Text) > photoNo Then
                      MsgBox "Select valid image number"
                      boolNoEvents = True
                        Me.TextBox1.Text = prevVal
                      boolNoEvents = False
                Else
                    Me.Image1.Picture = LoadPicture(fPath & arrPhoto(Me.TextBox1.Value - 1))
                    Me.Image1.PictureSizeMode = fmPictureSizeModeZoom
                End If
                prevVal = Me.TextBox1.Value
            End If
        Else
            Me.TextBox1.Text = ""
        End If
    End If
End Sub

如果有什么地方不够清楚,请不要犹豫,要求澄清。