ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 13391|回复: 25

[分享] 为Word右键增加“图片另存为选项”

[复制链接]

TA的精华主题

TA的得分主题

发表于 2013-8-19 23:01 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
近日看了怎么用VBA把WORD里的所有图片另存成文件??的帖子,心有所悟,于是便花了些时间来做了这个很久前就像实现的目标,近日终于做成功了,其实主要的代码还是来自于网络,我的工作就是将他们整合在了一起,并添加入右键,实现一键保存图片的目的。
本代码可达到:
1.保存浮动式图形;
2.保存嵌入式图形;
3.保存文本框
4.保存艺术字
如下:
1.jpg 2.jpg 3.jpg 按时.jpg
代码及测试文档见2楼。

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-8-19 23:04 | 显示全部楼层
'Thisdocument中:
Private Sub Document_Open()
    Dim cbn
    For Each cbn In Array("Inline Picture", "Floating Picture", "Shapes", "WordArt Context Menu")
        CommandBars(cbn).Reset
        With CommandBars(cbn).Controls.Add(msoControlButton, Before:=4)
            .Caption = "图片另存为"
            .FaceId = 307
            .OnAction = "图片另存为"
            .Style = msoButtonIconAndCaption
        End With
    Next
End Sub

'标准模块中:
Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function EmptyClipboard Lib "user32" () As Long
Private Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (pOPENFILENAME As OPENFILENAME) As Long
Public Const OFN_OVERWRITEPROMPT = &H2
Public Const OFN_HIDEREADONLY = &H4
Public Const OFN_PATHMUSTEXIST = &H800
Public Const OFN_FILEMUSTEXIST = &H1000
Public iClipBoardFormatNumber As Long
Enum picFormat
    pic_GIFformat = 1
    pic_jpgformat = 2
    pic_pngformat = 3
End Enum

Sub savePic(shp As Shape, picFormat As picFormat, sFileName As String)
'这个过程把工作表中的shape对象另存为图像文件,需要指定要导出的shape对象 - shp
'导出文件格式 - picFormat(有1,2,3三种选择,分别代表gif,jpg和png格式),目标文件名 - sFileName

    Set fs = Nothing
    Dim nClipsize As Long
    Dim hMem As Long
    Dim lpData As Long
    Dim sdata() As Byte
    shp.Select
    Selection.Copy
   
    OpenClipboard 0&
    If iClipBoardFormatNumber = 0 Then
        For i = 40000 To 60000
            If IsClipboardFormatAvailable(i) And IsClipboardFormatAvailable(i + 1) And IsClipboardFormatAvailable(i + 2) And IsClipboardFormatAvailable(i + 3) Then
                iClipBoardFormatNumber = i
                Exit For
            End If
        Next
    End If
On Error GoTo myError:
    hMem = GetClipboardData(iClipBoardFormatNumber + picFormat)
    If CBool(hMem) Then
        nClipsize = GlobalSize(hMem)
        lpData = GlobalLock(hMem)
        If lpData <> 0 Then
            ReDim sdata(0 To nClipsize) As Byte
            CopyMemory sdata(0), ByVal lpData, nClipsize
            Set fs = CreateObject("Scripting.FileSystemObject")
            If fs.fileExists(sFileName) Then
                Kill sFileName
            End If

            Open sFileName For Binary As #1
                Put #1, , sdata
            Close #1
        End If
        GlobalUnlock hMem
    Else
        GoTo myError
    End If

    EmptyClipboard
    CloseClipboard
    Exit Sub
myError:
    GlobalUnlock hMem
    EmptyClipboard
    CloseClipboard
    MsgBox "export failed!"
End Sub
Function 文件另存()
Dim i As Integer
Dim kuang As OPENFILENAME
Dim filename As String
kuang.lStructSize = Len(kuang)
kuang.hwndOwner = 0& 'ThisDocument.hwnd
kuang.hInstance = 0& 'App.hInstance
kuang.lpstrFile = Space(254)
kuang.nMaxFile = 255
kuang.lpstrFileTitle = Space(254)
kuang.nMaxFileTitle = 255
'kuang.lpstrInitialDir = App.Path
kuang.flags = 6148
'过虑对话框文件类型
kuang.lpstrFilter = "图像1(*.jpg)" & Chr$(0) & "*.jpg" & Chr$(0) & "图像2(*.bmp)" & Chr$(0) & "*.bmp" & Chr$(0) & "图像3(*.gif)" & Chr$(0) & "*.gif" & Chr$(0) & "所有文件(*.*)" & Chr$(0) & "*.*" & Chr$(0)
'对话框标题栏文字
kuang.lpstrTitle = "保存文件的路径及文件名..."
kuang.lpstrDefExt = kuang.lpstrFilter
kuang.flags = OFN_HIDEREADONLY + OFN_PATHMUSTEXIST + OFN_OVERWRITEPROMPT
i = GetSaveFileName(kuang) '显示保存文件对话框
If i >= 1 Then '取得对话中用户选择输入的文件名及路径
filename = kuang.lpstrFile
filename = Left(filename, InStr(filename, Chr(0)) - 1)
End If
If Len(filename) = 0 Then Exit Function
'保存代码
文件另存 = filename
End Function
Sub 图片另存为()
    Dim fn As String, pic As Long
    CloseClipboard
    fn = 文件另存
    If fn = "" Then Exit Sub
    If Split(fn, ".")(UBound(Split(fn, "."))) = "gif" Then
        pic = pic_jpgformat
    ElseIf Split(fn, ".")(UBound(Split(fn, "."))) = "jpg" Then
        pic = pic_jpgformat
    ElseIf Split(fn, ".")(UBound(Split(fn, "."))) = "png" Then
        pic = pic_pngformat
    End If
    If Selection.Type = wdSelectionInlineShape Then
        With Selection.InlineShapes(1).ConvertToShape
            .Select
            savePic Selection.ShapeRange(1), pic, fn
            .ConvertToInlineShape
        End With
    Else
        savePic Selection.ShapeRange(1), pic, fn
    End If
End Sub
test.rar (100.64 KB, 下载次数: 274)

TA的精华主题

TA的得分主题

发表于 2013-8-19 23:09 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
感谢楼主分享,学习了      

TA的精华主题

TA的得分主题

发表于 2014-7-25 13:41 | 显示全部楼层
zhanglei1371 发表于 2013-8-19 23:04
'Thisdocument中:
Private Sub Document_Open()
    Dim cbn

怎么用,复制文本到哪,怎么添加

TA的精华主题

TA的得分主题

发表于 2014-7-30 22:46 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2014-12-26 17:31 | 显示全部楼层
代码占用了剪贴板啊。
可否使用GDI+做到呢?

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-12-26 21:02 | 显示全部楼层
loquat 发表于 2014-12-26 17:31
代码占用了剪贴板啊。
可否使用GDI+做到呢?

我的水平你有不是不知道。菜鸟的本质一个。连GDI+的边缘都没到呢.....

TA的精华主题

TA的得分主题

发表于 2014-12-26 22:55 | 显示全部楼层
zhanglei1371 发表于 2014-12-26 21:02
我的水平你有不是不知道。菜鸟的本质一个。连GDI+的边缘都没到呢.....

Sub 图片导出0()
    Set imagestream = CreateObject("ADODB.Stream")
    With imagestream
        .Type = 1
        .Open
        .Write ActiveDocument.InlineShapes(1).Range.EnhMetaFileBits
        .SaveToFile "C:\图片导出0.jpg", 2
        .Close
    End With
    Set imagestream = Nothing
End Sub

TA的精华主题

TA的得分主题

发表于 2014-12-26 22:58 | 显示全部楼层
本帖最后由 loquat 于 2014-12-27 15:27 编辑

这两部分内容加到一起应该就可以释放剪贴板了。擦版主把我的帖子删掉了,是因为有外链?

  1. '*************************************************************************
  2. '**    作    者 :    laviewpbt
  3. '**    函 数 名 :    SaveStdPicToFile
  4. '**    输    入 :    Stdpic(StdPicture)        -   图象句柄
  5. '**             :    FileName(String)       -   保存路径
  6. '**             :    FileFormat(ImageFileFormat)       -   保存格式,默认jpg
  7. '**             :    JpgQuality(Long)          -   JPG图象质量
  8. '**             :    Resolution(Single)  -   设置分辨率
  9. '**    输    出 :    无
  10. '**    功能描述 :    把图象保存为JPG、PNG、GIF、BMP格式
  11. '**    修 改 人 :   laviewpbt
  12. '**    日    期 :    2012-03-02 22:56
  13. '**    版    本 :    终结版
  14. '*************************************************************************
  15. Option Explicit

  16. Private Const UnitPixel                  As Long = 2
  17. Private Const EncoderQuality             As String = "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"

  18. Private Type GdiplusStartupInput
  19.     GdiplusVersion           As Long
  20.     DebugEventCallback       As Long
  21.     SuppressBackgroundThread As Long
  22.     SuppressExternalCodecs   As Long
  23. End Type

  24. Private Enum EncoderParameterValueType
  25.     EncoderParameterValueTypeByte = 1
  26.     EncoderParameterValueTypeASCII = 2
  27.     EncoderParameterValueTypeShort = 3
  28.     EncoderParameterValueTypeLong = 4
  29.     EncoderParameterValueTypeRational = 5
  30.     EncoderParameterValueTypeLongRange = 6
  31.     EncoderParameterValueTypeUndefined = 7
  32.     EncoderParameterValueTypeRationalRange = 8
  33. End Enum

  34. Private Type EncoderParameter
  35.     GUID(0 To 3)        As Long
  36.     NumberOfValues      As Long
  37.     Type                As EncoderParameterValueType
  38.     Value               As Long
  39. End Type

  40. Private Type EncoderParameters
  41.     Count               As Long
  42.     Parameter           As EncoderParameter
  43. End Type

  44. Private Type ImageCodecInfo
  45.     ClassID(0 To 3)     As Long
  46.     FormatID(0 To 3)    As Long
  47.     CodecName           As Long
  48.     DllName             As Long
  49.     FormatDescription   As Long
  50.     FilenameExtension   As Long
  51.     MimeType            As Long
  52.     Flags               As Long
  53.     Version             As Long
  54.     SigCount            As Long
  55.     SigSize             As Long
  56.     SigPattern          As Long
  57.     SigMask             As Long
  58. End Type

  59. Private Declare Function GdiplusStartup Lib "gdiplus" (Token As Long, inputbuf As GdiplusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
  60. Private Declare Sub GdiplusShutdown Lib "gdiplus" (ByVal Token As Long)
  61. Private Declare Function GdipSaveImageToFile Lib "gdiplus" (ByVal hImage As Long, ByVal sFilename As Long, clsidEncoder As Any, encoderParams As Any) As Long
  62. Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal Image As Long) As Long
  63. Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As Long, ByVal hPal As Long, Bitmap As Long) As Long
  64. Private Declare Function GdipGetImageEncodersSize Lib "gdiplus" (numEncoders As Long, Size As Long) As Long
  65. Private Declare Function GdipGetImageEncoders Lib "gdiplus" (ByVal numEncoders As Long, ByVal Size As Long, Encoders As Any) As Long

  66. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
  67. Private Declare Function lstrlenW Lib "kernel32" (ByVal psString As Any) As Long
  68. Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpszProgID As Long, pCLSID As Any) As Long
  69. Private Declare Function GdipBitmapSetResolution Lib "gdiplus" (ByVal Bitmap As Long, ByVal xdpi As Single, ByVal ydpi As Single) As Long


  70. Public Enum ImageFileFormat
  71.     Bmp = 1
  72.     Jpg = 2
  73.     Png = 3
  74.     Gif = 4
  75. End Enum

  76. Public Function SaveStdPicToFile(Stdpic As StdPicture, ByVal FileName As String, _
  77.                               Optional ByVal FileFormat As ImageFileFormat = Jpg, _
  78.                               Optional ByVal JpgQuality As Long = 80, _
  79.                               Optional Resolution As Single) As Boolean
  80.                               
  81.     Dim CLSID(3)        As Long
  82.     Dim Bitmap          As Long
  83.     Dim Token           As Long
  84.     Dim Gsp             As GdiplusStartupInput

  85.     Gsp.GdiplusVersion = 1                      'GDI+ 1.0版本
  86.     GdiplusStartup Token, Gsp                   '初始化GDI+
  87.     GdipCreateBitmapFromHBITMAP Stdpic.Handle, Stdpic.hPal, Bitmap
  88.     If Bitmap <> 0 Then                          '说明我们成功的将StdPic对象转换为GDI+的Bitmap对象了
  89.         GdipBitmapSetResolution Bitmap, Resolution, Resolution
  90.         Select Case FileFormat
  91.         Case ImageFileFormat.Bmp
  92.             If Not GetEncoderClsID("Image/bmp", CLSID) = -1 Then
  93.                 SaveStdPicToFile = (GdipSaveImageToFile(Bitmap, StrPtr(FileName), CLSID(0), ByVal 0) = 0)
  94.             End If
  95.         Case ImageFileFormat.Jpg                    'JPG格式可以设置保存的质量
  96.             Dim aEncParams()        As Byte
  97.             Dim uEncParams          As EncoderParameters
  98.             If GetEncoderClsID("Image/jpeg", CLSID) <> -1 Then
  99.                 uEncParams.Count = 1                                        ' 设置自定义的编码参数,这里为1个参数
  100.                 If JpgQuality < 0 Then
  101.                     JpgQuality = 0
  102.                 ElseIf JpgQuality > 100 Then
  103.                     JpgQuality = 100
  104.                 End If
  105.                 ReDim aEncParams(1 To Len(uEncParams))
  106.                 With uEncParams.Parameter
  107.                     .NumberOfValues = 1
  108.                     .Type = EncoderParameterValueTypeLong                   ' 设置参数值的数据类型为长整型
  109.                     Call CLSIDFromString(StrPtr(EncoderQuality), .GUID(0))  ' 设置参数唯一标志的GUID,这里为编码品质
  110.                     .Value = VarPtr(JpgQuality)                                ' 设置参数的值:品质等级,最高为100,图像文件大小与品质成正比
  111.                 End With
  112.                 CopyMemory aEncParams(1), uEncParams, Len(uEncParams)
  113.                 SaveStdPicToFile = (GdipSaveImageToFile(Bitmap, StrPtr(FileName), CLSID(0), aEncParams(1)) = 0)
  114.             End If
  115.         Case ImageFileFormat.Png
  116.             If Not GetEncoderClsID("Image/png", CLSID) = -1 Then
  117.                 SaveStdPicToFile = (GdipSaveImageToFile(Bitmap, StrPtr(FileName), CLSID(0), ByVal 0) = 0)
  118.             End If
  119.         Case ImageFileFormat.Gif
  120.             If Not GetEncoderClsID("Image/gif", CLSID) = -1 Then                '如果原始的图像是24位,则这个函数会调用系统的调色板来将图像转换为8位,转换的效果会不尽人意,但也有可能系统不自动转换,保存失败
  121.                 SaveStdPicToFile = (GdipSaveImageToFile(Bitmap, StrPtr(FileName), CLSID(0), ByVal 0) = 0)
  122.             End If
  123.         End Select
  124.     End If
  125.     GdipDisposeImage Bitmap      '注意释放资源
  126.     GdiplusShutdown Token       '关闭GDI+。
  127. End Function


  128. Private Function GetEncoderClsID(strMimeType As String, ClassID() As Long) As Long
  129.     Dim Num         As Long
  130.     Dim Size        As Long
  131.     Dim I           As Long
  132.     Dim Info()      As ImageCodecInfo
  133.     Dim Buffer()    As Byte
  134.     GetEncoderClsID = -1
  135.     GdipGetImageEncodersSize Num, Size               '得到解码器数组的大小
  136.     If Size <> 0 Then
  137.        ReDim Info(1 To Num) As ImageCodecInfo       '给数组动态分配内存
  138.        ReDim Buffer(1 To Size) As Byte
  139.        GdipGetImageEncoders Num, Size, Buffer(1)            '得到数组和字符数据
  140.        CopyMemory Info(1), Buffer(1), (Len(Info(1)) * Num)     '复制类头
  141.        For I = 1 To Num             '循环检测所有解码
  142.            If (StrComp(PtrToStrW(Info(I).MimeType), strMimeType, vbTextCompare) = 0) Then         '必须把指针转换成可用的字符
  143.                CopyMemory ClassID(0), Info(I).ClassID(0), 16  '保存类的ID
  144.                GetEncoderClsID = I      '返回成功的索引值
  145.                Exit For
  146.            End If
  147.        Next
  148.     End If
  149. End Function

  150. Private Function PtrToStrW(ByVal lpsz As Long) As String
  151.     Dim Out         As String
  152.     Dim Length      As Long
  153.     Length = lstrlenW(lpsz)
  154.     If Length > 0 Then
  155.         Out = StrConv(String$(Length, vbNullChar), vbUnicode)
  156.         CopyMemory ByVal Out, ByVal lpsz, Length * 2
  157.         PtrToStrW = StrConv(Out, vbFromUnicode)
  158.     End If
  159. End Function
复制代码

TA的精华主题

TA的得分主题

发表于 2015-1-5 16:31 | 显示全部楼层
本帖最后由 loquat 于 2015-1-5 16:35 编辑
  1.     For Each cbn In Array("AutoText", "Drawing Canvas", "Organization Chart", "Diagram", "Frames", "Flowchart", "Inline Picture", "Floating Picture", "Shapes", "Inline Canvas", "Table Pictures", "AutoShapes", "Basic Shapes", "Insert Shape", "Picture", "WordArt Context Menu", "WordArt")
复制代码
稍作完善
原因是之前表格图片中没有右键菜单,顺便将其他内容查找添加了。
不知道是否一定有必要,但是应该很完整了。如果再有不显示右键的图片,请本帖讨论。。。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-21 22:33 , Processed in 0.040737 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表