Lưu hình ảnh trong tệp Excel ra thư mục

Liên hệ QC
Tôi tuân thủ nội quy khi đăng bài

Vui.Nguyen

Thành viên mới
Tham gia
23/8/24
Bài viết
4
Được thích
0
Chào anh chị trong Diễn đàn!
Mình có nhiều file báo giá cùng cấu trúc: Mã sản phẩm ở cột D và hình ảnh ở cột G (từ dòng 11 trở xuống).
Em có ý tưởng là chọn một hoặc nhiều tệp Excel cần lưu hình ảnh để mở file; Chọn thư mục lưu ảnh; Khi tệp Excel được mở, lần lượt di chuyển qua các sheet để tìm hình ảnh ở Cột G, nếu có hình ảnh thì lưu ảnh với tên là Mã sản phẩm ở Cột D với dòng tương ứng (Ví dụ Ô G11 có ảnh và ô D11 có mã hàng là "NMT2015" thì lưu ảnh với tên "NMT2015")
Nhờ anh chị hỗ trợ viết giúp code VBA để thực hiện ý tưởng trên.
Cảm ơn anh chị đã xem bài và mong muốn nhận được sự hỗ trợ từ anh chị!
 

File đính kèm

  • Luu ten anh theo ma hang.xlsx
    288 KB · Đọc: 12
Chào anh chị trong Diễn đàn!
Mình có nhiều file báo giá cùng cấu trúc: Mã sản phẩm ở cột D và hình ảnh ở cột G (từ dòng 11 trở xuống).
Em có ý tưởng là chọn một hoặc nhiều tệp Excel cần lưu hình ảnh để mở file; Chọn thư mục lưu ảnh; Khi tệp Excel được mở, lần lượt di chuyển qua các sheet để tìm hình ảnh ở Cột G, nếu có hình ảnh thì lưu ảnh với tên là Mã sản phẩm ở Cột D với dòng tương ứng (Ví dụ Ô G11 có ảnh và ô D11 có mã hàng là "NMT2015" thì lưu ảnh với tên "NMT2015")
Nhờ anh chị hỗ trợ viết giúp code VBA để thực hiện ý tưởng trên.
Cảm ơn anh chị đã xem bài và mong muốn nhận được sự hỗ trợ từ anh chị!
Tham khảo code trong file:
1/Đầu tiên tạo 1 folder có tên là Anh2 (bạn có thể thay tên theo bạn muốn- và phải thay đổi lại tên trong code) ,và được lưu cùng với file này Ví dụ (C:\Users\Admin\Downloads\)
2/ Nhấn nút " Chay code" và chọn những file cần lấy ảnh ( ....nhiều file báo giá cùng cấu trúc....)
3/ Kiểm tra kết quả ở Folder Anh2
 

File đính kèm

  • Chuyen anh thanh File .PJG theo ma hang.xlsm
    300.2 KB · Đọc: 6
Upvote 0
@Vui.Nguyen Mã dưới đây có thể lấy ảnh gốc trong tệp Excel của bạn. Không cần mở tệp với Excel.
Gọi ExportImages_files sẽ chọn tệp
Gọi ExportImages_folder sẽ chọn thư mục


Nếu có sự thay đổi cột dòng thì thay đổi tại dòng mã có "D", "G", 11

Chép mã vào VBA (mở VBA ALT+F11), tạo một module mới, dán mã, lưu dự án với dạng xlsm hoặc xlsb.
(***Dành cho lập trình nâng cao: chép vào Class Module để biên dịch sau)
JavaScript:
'                    _,
' ___   _   _  _ ___(_)
'/ __| / \ | \| | _ | |
'\__ \/ \ \| \\ | _ \ |
'|___/_/ \_|_|\_|___/_|
'


Private Const projectClassName = "ExportImages"
Private Const projectClassVersion = "1.0"
Option Compare Text
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

Sub ExportImages_files()
  Dim file, files, destDirectories$
  files = DialogExplorer(sFilter:="*.xlsx; *.xls; *.xlsm; *.xlsb")
  destDirectories = ""
  If IsArray(files) Then
    ExportImagesByFiles files, "D", "G", 11, destDirectories
  End If
End Sub
Sub ExportImages_folder()
  Dim folder$, files(), destDirectories$
  folder = DialogExplorer(FileDialog:=4)
  destDirectories = ""
  If folder <> "" Then
    ListAllFiles folder, files, glbFSO, True
    If (Not Not Files) Then  ExportImagesByFiles files, "D", "G", 11, destDirectories
  End If
End Sub

Private Sub ExportImagesByFiles(ByVal files, ByVal cellID$, ByVal cellImage$, ByVal startRow&, Optional ByVal destDirectories$)
  Dim file
  For Each file In files
    ExportImages file, cellID, cellImage, startRow, destDirectories
  Next
  ActiveWorkbook.FollowHyperlink destDirectories, , True
  MsgBox "Hoan thanh", , "ExportImages"
End Sub

Private Function ExportImages(ByVal fileName$, ByVal cellID$, ByVal cellImage$, ByVal startRow&, Optional destDirectories$) As Boolean
  On Error Resume Next
  Dim file$
  Dim s$, s1$, s2$, s3$, s4$, re, re1, re2, re3, oFile As Object
  Dim oFolder As Object, b As Boolean
  Dim oSh, ms, ms2, FSO As Object, tPath, tPath2, fn$, fn2$, app As Object
  Dim it, ZipFile, Ext$, xl_type&, i%
  Dim fName$, cc&, cc2&, adr$, imExt$, DOM
  adr = cellID 'Split(cellID.EntireColumn.Address(0, 0), ":")(0)
  With ThisWorkbook.sheets(1)
    cc = .Range(cellID & ":" & cellID).Column: cc2 = .Range(cellImage & ":" & cellImage).Column
  End With
  Set re = glbRegex
  Set re1 = glbRegex
  Set re2 = glbRegex(False)
  Set re3 = glbRegex(False)
  Set FSO = glbFSO
  Set oSh = glbShellA
  Set DOM = glbXMLDOM
  '-----------------------------------------------
  file = fileName
  Select Case True
  Case file Like "*.xla": xl_type = 18: Ext = ".xla": b = True
  Case file Like "*.xlsb": xl_type = 50: Ext = ".xlsb": b = True
  Case file Like "*.xlsx": xl_type = 51: Ext = ".xlsx"
  Case file Like "*.xlsm": xl_type = 52: Ext = ".xlsm"
  Case file Like "*.xlam": xl_type = 55: Ext = ".xlam"
  Case file Like "*.xls": xl_type = 56: Ext = ".xls": b = True
  Case Else: Exit Function
  End Select
 
  If Not destDirectories Like "*[\/]" And destDirectories <> "" Then destDirectories = destDirectories & "\"
  With FSO
    Set oFile = .GetFile(file)
    If oFile Is Nothing Then Exit Function
    fn = oFile.Name
    If b Then fn = Replace(fn, Ext, ".xlsx", , , 1): Ext = ".xlsx"
    fn2 = Left$(fn, Len(fn) - Len(Ext))
    If destDirectories = "" Then destDirectories = oFile.ParentFolder.Path & "\images\"
    CreateFolder destDirectories, FSO
    tPath = Environ$("temp") & "\VBE\exportImages\"
    tPath2 = tPath & fn2 & "\xl\"
    CreateFolder tPath2, FSO
    ZipFile = tPath & fn2 & "\" & fn & ".zip"
    If b Then
      Set app = CreateObject("Excel.Application")
      With app
        .EnableEvents = False
        .DisplayAlerts = False
        .Calculation = -4135
        With .Workbooks.Open(fileName:=file, UpdateLinks:=False, ReadOnly:=True)
          .SaveAs ZipFile, 51: .Close False
        End With
        .Quit
      End With
      Set app = Nothing
    Else
      .copyFile file, ZipFile, True
    End If
  End With
  err.Clear: DoEvents:
  oSh.Namespace(CVar(tPath2)).movehere oSh.Namespace(CVar(ZipFile & "\xl\")).items, 4 Or 16
  Dim wbxml$, pwbxml$, pwbrels$, mmm, shrd
  Dim shName$, shID$, ID$, shXML$, imageID$, j&, r&, c&
  fName = tPath2 & "workbook.xml": GoSub readfile: pwbxml = s
  fName = tPath2 & "_rels\workbook.xml.rels": GoSub readfile: pwbrels = s
  fName = tPath2 & "sharedStrings.xml": GoSub readfile: shrd = s
  're.Pattern = "<!--(.*?)-->|\r?\n\s*\B"
  re.Pattern = "<sheet [^<>]*name=""((?:""""|[^""])+)"" [^<>]*sheetId=""([^""]+)"" [^<>]*r:id=""([^""]+)""[^<>]*/>"
  re1.Pattern = "<xdr:from><xdr:col>(\d+)</xdr:col>.+?<xdr:row>(\d+)</xdr:row>.+?<xdr:cNvPr[^<>]* id=""([^""]*)""[^<>]* name=""([^""]*)""[^<>]*>.+?<a:blip [^<>]+r:embed=""([^""]+)""[^<>/]*/>"
  re3.Pattern = "<Relationship[^<>]* Id=""([^""]+)"" [^<>]*Target=""\.\.\/drawings\/([^ ]+\.xml)""[^<>]*\/>"
  Set ms = re.Execute(pwbxml)
  If ms.count = 0 Then GoTo E
  For i = 1 To ms.count
    Set mmm = ms(i - 1).submatches
    shName = mmm(0): shID = mmm(1): ID = mmm(2)
    With re2
      .Pattern = "<Relationship[^<>]* Id=""" & ID & """ [^<>]*Target=""worksheets\/([^ ]+\.xml)""[^<>]*\/>"
      shXML = .Execute(pwbrels)(0).submatches(0)
      fName = tPath2 & "worksheets\" & shXML: GoSub readfile: s1 = s
      fName = Replace$(fName, "\worksheets\", "\worksheets\_rels\") & ".rels": GoSub readfile: s2 = s
      fName = tPath2 & "drawings\" & re3.Execute(s2)(0).submatches(1): GoSub readfile: s3 = s
      fName = Replace$(fName, "\drawings\", "\drawings\_rels\") & ".rels": GoSub readfile: s4 = s
      Set ms2 = re1.Execute(s3)
      For j = 1 To ms2.count
        Set mmm = ms2(j - 1).submatches: r = mmm(1) + 1: c = mmm(0) + 1: imageID = mmm(4)
        If r >= startRow And c = cc2 Then
          .Pattern = "<Relationship[^<>]* Id=""" & imageID & """ [^<>]*Target=""\.\.\/media\/([^""/>]+(\.[^""/>]+))""[^<>]*\/>"
          Set mmm = .Execute(s4)(0).submatches: fn2 = tPath2 & "media\" & mmm(0): imExt = mmm(1)
          .Pattern = "<c r=""" & adr & CStr(r) & """[^>]+t=""([^""]*)"">(?:<f(?: [^>]+)?>.*?</f>)?<v>(.*?)</v></c>"
          err.Clear: Set mmm = .Execute(s1)(0).submatches
          fn = mmm(1)
          If mmm(0) = "str" Then
          Else
            .Pattern = "(?:<si><t[^>]*>(?:\r|\n|.)+?</t></si>){" & CStr(CLng(fn)) & "}<si><t[^>]*>((?:\r|\n|.)+?)</t></si>"
            fn = .Execute(shrd)(0).submatches(0)
          End If
          DoEvents: FSO.MoveFile fn2, destDirectories & Replace$(fn, vbNewLine, " ") & imExt
        End If
      Next
    End With
  Next
  ExportImages = True
E:
  FSO.GetFolder(tPath).Delete
Exit Function
readfile:
  DOM.Load fName: s = DOM.xml
Return
End Function

Private Function CreateFolder(ByVal folderPath As String, Optional ByRef FileSystem As Object) As Boolean
  Dim FolderArray, Tmp$, i As Integer, UB As Integer, tFolder$
  tFolder = folderPath
  If Right(tFolder, 1) = "\" Then tFolder = Left(tFolder, Len(tFolder) - 1)
  If tFolder Like "\\*\*" Then tFolder = Strings.Replace(tFolder, "\", "@", 1, 3)
  FolderArray = Split(tFolder, "\")
  If FileSystem Is Nothing Then Set FileSystem = glbFSO
  On Error GoTo Ends
  FolderArray(0) = Strings.Replace(FolderArray(0), "@", "\", 1, 3)
  UB = UBound(FolderArray)
  With FileSystem
    For i = 0 To UB
      Tmp = Tmp & FolderArray(i) & "\"
      If Not .FolderExists(Tmp) Then DoEvents: .CreateFolder (Tmp)
      CreateFolder = (i = UB) And Len(FolderArray(i)) > 0 And FolderArray(i) <> " "
    Next
  End With
Ends:
End Function

Private Function glbRegex(Optional bglobal = True, Optional IgnoreCase = True, Optional MultiLine = True) As Object
  Set glbRegex = CreateObject("VBScript.RegExp")
  With glbRegex: .Global = bglobal: .IgnoreCase = IgnoreCase: .MultiLine = MultiLine: End With
End Function

Private Function glbFSO() As Object
  Set glbFSO = CreateObject("Scripting.FileSystemObject")
End Function

Private Function glbShellA() As Object
  Set glbShellA = CreateObject("Shell.Application")
End Function

Private Function StandardPath(ByVal Path As String) As String
    StandardPath = Path & IIf(Right(Path, 1) <> "\", "\", "")
End Function

Private Function glbXMLDOM() As Object
  Set glbXMLDOM = CreateObject("MSXML2.DOMDocument.6.0")
End Function

Private Function ThisPath(Optional ByVal fileName As String) As String
    ThisPath = ThisWorkbook.Path & "\" & fileName
End Function
Private Function DialogExplorer(Optional folderPath$, _
                        Optional sDesc$ = "All File", _
                        Optional sFilter$ = "*.*", _
                        Optional Title$ = "File Open", _
                        Optional FileDialog& = 1, _
                        Optional InitialView& = 2, _
                        Optional ButtonName$ = "&Select", _
                        Optional MultiSelect As Boolean = -1) As Variant
  DialogExplorer = ""
  Dim arr(), k&, it
  With Application.FileDialog(FileDialog) '1|4'
    If ButtonName <> vbNullString Then .ButtonName = ButtonName
    If FileDialog = 1 Then
      .Filters.Clear
      .Filters.Add sDesc, sFilter
      If sDesc$ <> "All File" Then .Filters.Add "All File", "*.*"
    End If
    If Title <> vbNullString Then .Title = Title
    .InitialView = InitialView 'msoFileDialogViewDetails'
    .AllowMultiSelect = IIf(FileDialog = 4, False, MultiSelect)
    If folderPath <> vbNullString Then
      .InitialFileName = folderPath
    Else
      .InitialFileName = ThisWorkbook.Path ' Application.DefaultFilePath
    End If
    If .Show = -1 Then
      If FileDialog = 4 Or Not MultiSelect Then
        DialogExplorer = .SelectedItems(1)
      Else
        For Each it In .SelectedItems
          k = k + 1: ReDim Preserve arr(1 To k): arr(k) = it:
        Next it
        DialogExplorer = arr
      End If
    End If
    If FileDialog = 1 Then .Filters.Clear
  End With
End Function

Private Sub ListAllFiles(ByVal Paths, _
                 ByRef files(), _
        Optional ByVal FSO As Object, _
        Optional ByVal IncludeSubfolders As Boolean = False)
  On Error Resume Next
  Dim r As Long, c%
  Dim ItemName As String
  Dim Item, folder, oFolder
  '-------------------------------------------
  If Not IsArray(Paths) Then Paths = Array(Paths)
  r = 0: r = UBound(files)
  For Each folder In Paths
    Set oFolder = FSO.GetFolder(folder)
    For Each Item In oFolder.files
      ItemName = LCase(Item.Name)
      If Not ItemName Like "[~.]*" Then
        Select Case True
        Case ItemName Like "*.xlsm", ItemName Like "*.xlsx", ItemName Like "*.xls", ItemName Like "*.xlsb"
          r = r + 1: ReDim Preserve files(1 To r): files(r) = Item.Path
        End Select
      End If
    Next Item
    If IncludeSubfolders Then
      For Each Item In oFolder.SubFolders
        Call ListAllFiles(Item.Path, files, FSO, True)
      Next Item
    End If
  Next folder
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Tham khảo code trong file:
1/Đầu tiên tạo 1 folder có tên là Anh2 (bạn có thể thay tên theo bạn muốn- và phải thay đổi lại tên trong code) ,và được lưu cùng với file này Ví dụ (C:\Users\Admin\Downloads\)
2/ Nhấn nút " Chay code" và chọn những file cần lấy ảnh ( ....nhiều file báo giá cùng cấu trúc....)
3/ Kiểm tra kết quả ở Folder Anh2
Chào anh @HUONGHCKT
Em chạy code cho ra kết quả đúng tên tương ứng với từng ảnh. Tuy nhiên gặp vấn đề là sử dụng ảnh được lưu chèn ngược lại file excel trong biểu mẫu báo giá thì ảnh có dư 1 vùng trắng bên dưới (ảnh đính kèm).
Nếu được, nhờ anh kiểm tra và sửa lại giúp em ạ!
Cảm ơn anh!
 

File đính kèm

  • Ket qua_Anh theo ma hang.jpg
    Ket qua_Anh theo ma hang.jpg
    68.6 KB · Đọc: 8
Upvote 0
@Vui.Nguyen Mã dưới đây có thể lấy ảnh gốc trong tệp Excel của bạn. Không cần mở tệp với Excel.
Gọi ExportImages_files sẽ chọn tệp
Gọi ExportImages_folder sẽ chọn thư mục


Nếu có sự thay đổi cột dòng thì thay đổi tại dòng mã có "D", "G", 11

Chép mã vào VBA (mở VBA ALT+F11), tạo một module mới, dán mã, lưu dự án với dạng xlsm hoặc xlsb.
(***Dành cho lập trình nâng cao: chép vào Class Module để biên dịch sau)
JavaScript:
'                    _,
' ___   _   _  _ ___(_)
'/ __| / \ | \| | _ | |
'\__ \/ \ \| \\ | _ \ |
'|___/_/ \_|_|\_|___/_|
'


Private Const projectClassName = "ExportImages"
Private Const projectClassVersion = "1.0"
Option Compare Text
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

Sub ExportImages_files()
  Dim file, files, destDirectories$
  files = DialogExplorer(sFilter:="*.xlsx; *.xls; *.xlsm; *.xlsb")
  destDirectories = ""
  If IsArray(files) Then
    ExportImagesByFiles files, "D", "G", 11, destDirectories
  End If
End Sub
Sub ExportImages_folder()
  Dim folder$, files(), destDirectories$
  folder = DialogExplorer(FileDialog:=4)
  destDirectories = ""
  If folder <> "" Then
    ListAllFiles folder, files, glbFSO, True
    ExportImagesByFiles files, "D", "G", 11, destDirectories
  End If
End Sub

Private Sub ExportImagesByFiles(ByVal files, ByVal cellID$, ByVal cellImage$, ByVal startRow&, Optional ByVal destDirectories$)
  Dim file
  For Each file In files
    ExportImages file, cellID, cellImage, startRow, destDirectories
  Next
  ActiveWorkbook.FollowHyperlink destDirectories, , True
  MsgBox "Hoan thanh", , "ExportImages"
End Sub

Private Function ExportImages(ByVal fileName$, ByVal cellID$, ByVal cellImage$, ByVal startRow&, Optional destDirectories$) As Boolean
  On Error Resume Next
  Dim file$
  Dim s$, s1$, s2$, s3$, s4$, re, re1, re2, re3, oFile As Object
  Dim oFolder As Object, b As Boolean
  Dim oSh, ms, ms2, FSO As Object, tPath, tPath2, fn$, fn2$, app As Object
  Dim it, ZipFile, Ext$, xl_type&, i%
  Dim fName$, cc&, cc2&, adr$, imExt$, DOM
  adr = cellID 'Split(cellID.EntireColumn.Address(0, 0), ":")(0)
  With ThisWorkbook.sheets(1)
    cc = .Range(cellID & ":" & cellID).Column: cc2 = .Range(cellImage & ":" & cellImage).Column
  End With
  Set re = glbRegex
  Set re1 = glbRegex
  Set re2 = glbRegex(False)
  Set re3 = glbRegex(False)
  Set FSO = glbFSO
  Set oSh = glbShellA
  Set DOM = glbXMLDOM
  '-----------------------------------------------
  file = fileName
  Select Case True
  Case file Like "*.xla": xl_type = 18: Ext = ".xla": b = True
  Case file Like "*.xlsb": xl_type = 50: Ext = ".xlsb": b = True
  Case file Like "*.xlsx": xl_type = 51: Ext = ".xlsx"
  Case file Like "*.xlsm": xl_type = 52: Ext = ".xlsm"
  Case file Like "*.xlam": xl_type = 55: Ext = ".xlam"
  Case file Like "*.xls": xl_type = 56: Ext = ".xls": b = True
  Case Else: Exit Function
  End Select
 
  If Not destDirectories Like "*[\/]" And destDirectories <> "" Then destDirectories = destDirectories & "\"
  With FSO
    Set oFile = .GetFile(file)
    If oFile Is Nothing Then Exit Function
    fn = oFile.Name
    If b Then fn = Replace(fn, Ext, ".xlsx", , , 1): Ext = ".xlsx"
    fn2 = Left$(fn, Len(fn) - Len(Ext))
    If destDirectories = "" Then destDirectories = oFile.ParentFolder.Path & "\images\"
    CreateFolder destDirectories, FSO
    tPath = Environ$("temp") & "\VBE\exportImages\"
    tPath2 = tPath & fn2 & "\xl\"
    CreateFolder tPath2, FSO
    ZipFile = tPath & fn2 & "\" & fn & ".zip"
    If b Then
      Set app = CreateObject("Excel.Application")
      With app
        .EnableEvents = False
        .DisplayAlerts = False
        .Calculation = -4135
        With .Workbooks.Open(fileName:=file, UpdateLinks:=False, ReadOnly:=True)
          .SaveAs ZipFile, 51: .Close False
        End With
        .Quit
      End With
      Set app = Nothing
    Else
      .copyFile file, ZipFile, True
    End If
  End With
  err.Clear: DoEvents:
  oSh.Namespace(CVar(tPath2)).movehere oSh.Namespace(CVar(ZipFile & "\xl\")).items, 4 Or 16
  Dim wbxml$, pwbxml$, pwbrels$, mmm, shrd
  Dim shName$, shID$, ID$, shXML$, imageID$, j&, r&, c&
  fName = tPath2 & "workbook.xml": GoSub readfile: pwbxml = s
  fName = tPath2 & "_rels\workbook.xml.rels": GoSub readfile: pwbrels = s
  fName = tPath2 & "sharedStrings.xml": GoSub readfile: shrd = s
  're.Pattern = "<!--(.*?)-->|\r?\n\s*\B"
  re.Pattern = "<sheet [^<>]*name=""((?:""""|[^""])+)"" [^<>]*sheetId=""([^""]+)"" [^<>]*r:id=""([^""]+)""[^<>]*/>"
  re1.Pattern = "<xdr:from><xdr:col>(\d+)</xdr:col>.+?<xdr:row>(\d+)</xdr:row>.+?<xdr:cNvPr[^<>]* id=""([^""]*)""[^<>]* name=""([^""]*)""[^<>]*>.+?<a:blip [^<>]+r:embed=""([^""]+)""[^<>/]*/>"
  re3.Pattern = "<Relationship[^<>]* Id=""([^""]+)"" [^<>]*Target=""\.\.\/drawings\/([^ ]+\.xml)""[^<>]*\/>"
  Set ms = re.Execute(pwbxml)
  If ms.count = 0 Then GoTo E
  For i = 1 To ms.count
    Set mmm = ms(i - 1).submatches
    shName = mmm(0): shID = mmm(1): ID = mmm(2)
    With re2
      .Pattern = "<Relationship[^<>]* Id=""" & ID & """ [^<>]*Target=""worksheets\/([^ ]+\.xml)""[^<>]*\/>"
      shXML = .Execute(pwbrels)(0).submatches(0)
      fName = tPath2 & "worksheets\" & shXML: GoSub readfile: s1 = s
      fName = Replace$(fName, "\worksheets\", "\worksheets\_rels\") & ".rels": GoSub readfile: s2 = s
      fName = tPath2 & "drawings\" & re3.Execute(s2)(0).submatches(1): GoSub readfile: s3 = s
      fName = Replace$(fName, "\drawings\", "\drawings\_rels\") & ".rels": GoSub readfile: s4 = s
      Set ms2 = re1.Execute(s3)
      For j = 1 To ms2.count
        Set mmm = ms2(j - 1).submatches: r = mmm(1) + 1: c = mmm(0) + 1: imageID = mmm(4)
        If r >= startRow And c = cc2 Then
          .Pattern = "<Relationship[^<>]* Id=""" & imageID & """ [^<>]*Target=""\.\.\/media\/([^""/>]+(\.[^""/>]+))""[^<>]*\/>"
          Set mmm = .Execute(s4)(0).submatches: fn2 = tPath2 & "media\" & mmm(0): imExt = mmm(1)
          .Pattern = "<c r=""" & adr & CStr(r) & """[^>]+t=""([^""]*)"">(?:<f(?: [^>]+)?>.*?</f>)?<v>(.*?)</v></c>"
          err.Clear: Set mmm = .Execute(s1)(0).submatches
          fn = mmm(1)
          If mmm(0) = "str" Then
          Else
            .Pattern = "(?:<si><t[^>]*>(?:\r|\n|.)+?</t></si>){" & CStr(CLng(fn)) & "}<si><t[^>]*>((?:\r|\n|.)+?)</t></si>"
            fn = .Execute(shrd)(0).submatches(0)
          End If
          DoEvents: FSO.MoveFile fn2, destDirectories & Replace$(fn, vbNewLine, " ") & imExt
        End If
      Next
    End With
  Next
  ExportImages = True
E:
  FSO.GetFolder(tPath).Delete
Exit Function
readfile:
  DOM.Load fName: s = DOM.xml
Return
End Function

Private Function CreateFolder(ByVal folderPath As String, Optional ByRef FileSystem As Object) As Boolean
  Dim FolderArray, Tmp$, i As Integer, UB As Integer, tFolder$
  tFolder = folderPath
  If Right(tFolder, 1) = "\" Then tFolder = Left(tFolder, Len(tFolder) - 1)
  If tFolder Like "\\*\*" Then tFolder = Strings.Replace(tFolder, "\", "@", 1, 3)
  FolderArray = Split(tFolder, "\")
  If FileSystem Is Nothing Then Set FileSystem = glbFSO
  On Error GoTo Ends
  FolderArray(0) = Strings.Replace(FolderArray(0), "@", "\", 1, 3)
  UB = UBound(FolderArray)
  With FileSystem
    For i = 0 To UB
      Tmp = Tmp & FolderArray(i) & "\"
      If Not .FolderExists(Tmp) Then DoEvents: .CreateFolder (Tmp)
      CreateFolder = (i = UB) And Len(FolderArray(i)) > 0 And FolderArray(i) <> " "
    Next
  End With
Ends:
End Function

Private Function glbRegex(Optional bglobal = True, Optional IgnoreCase = True, Optional MultiLine = True) As Object
  Set glbRegex = CreateObject("VBScript.RegExp")
  With glbRegex: .Global = bglobal: .IgnoreCase = IgnoreCase: .MultiLine = MultiLine: End With
End Function

Private Function glbFSO() As Object
  Set glbFSO = CreateObject("Scripting.FileSystemObject")
End Function

Private Function glbShellA() As Object
  Set glbShellA = CreateObject("Shell.Application")
End Function

Private Function StandardPath(ByVal Path As String) As String
    StandardPath = Path & IIf(Right(Path, 1) <> "\", "\", "")
End Function

Private Function glbXMLDOM() As Object
  Set glbXMLDOM = CreateObject("MSXML2.DOMDocument.6.0")
End Function

Private Function ThisPath(Optional ByVal fileName As String) As String
    ThisPath = ThisWorkbook.Path & "\" & fileName
End Function
Private Function DialogExplorer(Optional folderPath$, _
                        Optional sDesc$ = "All File", _
                        Optional sFilter$ = "*.*", _
                        Optional Title$ = "File Open", _
                        Optional FileDialog& = 1, _
                        Optional InitialView& = 2, _
                        Optional ButtonName$ = "&Select", _
                        Optional MultiSelect As Boolean = -1) As Variant
  DialogExplorer = ""
  Dim arr(), k&, it
  With Application.FileDialog(FileDialog) '1|4'
    If ButtonName <> vbNullString Then .ButtonName = ButtonName
    If FileDialog = 1 Then
      .Filters.Clear
      .Filters.Add sDesc, sFilter
      If sDesc$ <> "All File" Then .Filters.Add "All File", "*.*"
    End If
    If Title <> vbNullString Then .Title = Title
    .InitialView = InitialView 'msoFileDialogViewDetails'
    .AllowMultiSelect = IIf(FileDialog = 4, False, MultiSelect)
    If folderPath <> vbNullString Then
      .InitialFileName = folderPath
    Else
      .InitialFileName = ThisWorkbook.Path ' Application.DefaultFilePath
    End If
    If .Show = -1 Then
      If FileDialog = 4 Or Not MultiSelect Then
        DialogExplorer = .SelectedItems(1)
      Else
        For Each it In .SelectedItems
          k = k + 1: ReDim Preserve arr(1 To k): arr(k) = it:
        Next it
        DialogExplorer = arr
      End If
    End If
    If FileDialog = 1 Then .Filters.Clear
  End With
End Function

Private Sub ListAllFiles(ByVal Paths, _
                 ByRef files(), _
        Optional ByVal FSO As Object, _
        Optional ByVal IncludeSubfolders As Boolean = False)
  On Error Resume Next
  Dim r As Long, c%
  Dim ItemName As String
  Dim Item, folder, oFolder
  '-------------------------------------------
  r = 0: r = UBound(files)
  For Each folder In Paths
    Set oFolder = FSO.GetFolder(folder)
    For Each Item In oFolder.files
      ItemName = LCase(Item.Name)
      If Not ItemName Like "[~.]*" Then
        Select Case True
        Case ItemName Like "*.xlsm", ItemName Like "*.xlsx", ItemName Like "*.xls", ItemName Like "*.xlsb"
          r = r + 1: ReDim Preserve files(1 To r): files(r) = Item.Path
        End Select
      End If
    Next Item
    If IncludeSubfolders Then
      For Each Item In oFolder.SubFolders
        Call ListAllFiles(Item.Path, files, FSO, True)
      Next Item
    End If
  Next folder
End Sub
Chào anh @HeSanbi ,
Em gọi ExportImages_files để chọn tệp và đã lưu được ảnh theo đúng mong muốn. Khi gọi ExportImages_folder thì sau khi chọn thư mục có chứa file excel mẫu em đã đính kèm ở bài 1 thì code hiển thị thông báo lỗi: Run-time error '92': For loop not intialized.
Em bấm Debug thì chỉ dẫn đến Private Sub ExportImagesByFiles tại dòng lệnh for each file với thông tin "file = Empty".
Nếu được, nhờ anh hỗ trợ giúp thêm giúp em.
Cảm ơn anh!
 
Upvote 0
Bạn chép lại mã tại bài trên
 
Upvote 0
Chào anh @HUONGHCKT
Em chạy code cho ra kết quả đúng tên tương ứng với từng ảnh. Tuy nhiên gặp vấn đề là sử dụng ảnh được lưu chèn ngược lại file excel trong biểu mẫu báo giá thì ảnh có dư 1 vùng trắng bên dưới (ảnh đính kèm).
Nếu được, nhờ anh kiểm tra và sửa lại giúp em ạ!
Cảm ơn anh!
Chưa xem lại kỹ được nhưng có thể lấy ảnh để gán vào Excel thì rất có thể phải có code để ảnh vừa khít ô.
Vầ đấy lại là 1 bài toán hoàn toàn khác.
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom