word+ppt vba

word 编号黑框问题

Sub test()
    For Each templ In ActiveDocument.ListTemplates
    For Each lev In templ.ListLevels
    lev.Font.Reset
    Next lev
    Next templ
End Sub

导出PPT备注

感谢知乎大佬

作者:Emrys
链接:https://www.zhihu.com/question/547915281/answer/2655781983


' 如果不想要导出全部幻灯片的备注,可以在代码里面修改页码范围,即把下面的代码
' For i = 1 To num_slides修改成你想要的范围(如第 4 页 到第 8 页):For i = 4 To 8Sub ExportNote()
Sub ExportText()
  Dim oPres As Presentation
  Dim oSlides As Slides
  Dim oSld As Slide         'Slide Object
  Dim oShp As Shape         'Shape Object
  Dim iFile As Integer      'File handle for output
  iFile = FreeFile          'Get a free file number
  Dim PathSep As String
  Dim path As String
  Dim FileNum As Integer
  Dim sTempString As String

  Set oPres = ActivePresentation
  Set oSlides = oPres.Slides
  filename = oPres.FullName

  #If Mac Then
    PathSep = "/"
    path = MacScript("return POSIX path of (path to desktop folder)")
    if Right(path, 1) = PathSep And Len(path) > 1 Then
        path = Mid(path, 1, Len(path) - 1)
    End If
  #Else
    PathSep = "\"
    path = oPres.Path
  #End If

  FileNum = FreeFile

  'Open output file
  ' NOTE:  errors here if file hasn't been saved
  Open path & PathSep & filename & ".txt" For Output As FileNum

  On Error GoTo ErrorHandler   ' Enable error-handling routine.

  num_slides = ActivePresentation.Slides.Count

  For i = 1 To num_slides
    Set oSld = ActivePresentation.Slides(i)
    Print #iFile, "(Page " & CStr(oSld.SlideNumber) & ")" & vbNewLine

    Print #iFile, oSld.NotesPage.Shapes.Placeholders(2).TextFrame.TextRange

    Print #iFile, "--------------------------" & vbNewLine & vbNewLine & vbNewLine
    Next i
  Close #iFile

  MsgBox "文件已创建在'" & path & PathSep & filename & ".txt'"

  Exit Sub       ' Exit to avoid handler.
  ErrorHandler:  ' Error-handling routine.
    Print #iFile, "(Error)" & vbNewLine
    Resume Next  ' Resume execution at the statement immediately
                 ' following the statement where the error occurred.
End Sub




' ' Windows 上从单页或多页 PPT 中提取所有文本框内的文字


' 作者:Emrys
' 链接:https://www.zhihu.com/question/387555935/answer/1160380698
' 来源:知乎
' 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

' 运行之后,就会在 PPT 同目录下生成与 PTT 文件同名的 .txt 文件,其中内容格式如下:Slide: [页码编号][这一页第1个形状的名称]: [文本内容][这一页第2个形状的名称]: [文本内容]Slide: [页码编号][这一页第1个形状的名称]: [文本内容]……<img src="https://pic4.zhimg.com/v2-b21f804fae7fb6313caac4e29e094293_b.jpg" data-size="normal" data-rawwidth="1497" data-rawheight="877" data-default-watermark-src="https://pic1.zhimg.com/v2-8693b062705e0c7c6b9a77165d6f20e8_b.jpg" class="origin_image zh-lightbox-thumb" width="1497" data-original="https://pic4.zhimg.com/v2-b21f804fae7fb6313caac4e29e094293_r.jpg"/>导出文本的格式上面用到的 VBA 代码如下(也适用于 Mac):如果不想要导出全部幻灯片的文本,可以在代码里面修改页码范围,即把下面的代码For i = 1 To num_slides修改成你想要的范围(如第 4 页 到第 8 页):For i = 4 To 8Sub ExportText()
  Dim oPres As Presentation
  Dim oSlides As Slides
  Dim oSld As Slide         'Slide Object
  Dim oShp As Shape         'Shape Object
  Dim iFile As Integer      'File handle for output
  iFile = FreeFile          'Get a free file number
  Dim PathSep As String
  Dim FileNum As Integer
  Dim sTempString As String

  #If Mac Then
    PathSep = "/"
  #Else
    PathSep = "\"
  #End If

  Set oPres = ActivePresentation
  Set oSlides = oPres.Slides

  FileNum = FreeFile

  'Open output file
  ' NOTE:  errors here if file hasn't been saved
  'Open oPres.Path & PathSep & "AllText.txt" For Output As FileNum
  Open oPres.Path & PathSep & oPres.Name & ".txt" For Output As FileNum
  
  num_slides = ActivePresentation.Slides.Count

  For i = 1 To num_slides
    Set oSld = ActivePresentation.Slides(i)
    Print #iFile, "Slide:" & vbTab & CStr(oSld.SlideNumber)

    For Each oShp In oSld.Shapes
      'Check to see if shape has a text frame and text
      If oShp.HasTextFrame And oShp.TextFrame.HasText Then
        If oShp.Type = msoPlaceholder Then
            Select Case oShp.PlaceholderFormat.Type
                Case Is = ppPlaceholderTitle, ppPlaceholderCenterTitle
                    Print #iFile, "标题:" & vbTab & oShp.TextFrame.TextRange
                Case Is = ppPlaceholderBody
                    Print #iFile, "正文:" & vbTab & oShp.TextFrame.TextRange
                Case Is = ppPlaceholderSubtitle
                    Print #iFile, "副标题:" & vbTab & oShp.TextFrame.TextRange
                Case Else
                    Print #iFile, "其他占位符:" & vbTab & oShp.TextFrame.TextRange
            End Select
        Else
            Print #iFile, vbTab & oShp.TextFrame.TextRange
        End If  ' msoPlaceholder
      Else  ' it doesn't have a textframe - it might be a group that contains text so:
        If oShp.Type = msoGroup Then
            sTempString = TextFromGroupShape(oShp)
            If Len(sTempString) > 0 Then
                Print #iFile, sTempString
            End If
        End If
      End If    ' Has text frame/Has text
    Next oShp
    
    Print #iFile, vbCrLf
    Next i
  Close #iFile

  'MsgBox "文件已创建在 '" & oPres.Path & PathSep & "AllText.txt'"
  MsgBox "文件已创建在 '" & oPres.Path & PathSep & oPres.Name & ".txt'"
End Sub

Function TextFromGroupShape(oSh As Shape) As String
' Returns the text from the shapes in a group
' and recursively, text within shapes within groups within groups etc.

    Dim oGpSh As Shape
    Dim sTempText As String

    If oSh.Type = msoGroup Then
        For Each oGpSh In oSh.GroupItems
            With oGpSh
                If .Type = msoGroup Then
                    sTempText = sTempText & TextFromGroupShape(oGpSh)
                Else
                    If .HasTextFrame Then
                        If .TextFrame.HasText Then
                            sTempText = sTempText & "(Gp:) " & .TextFrame.TextRange.Text & vbCrLf
                        End If
                    End If
                End If
            End With
        Next
    End If

    TextFromGroupShape = sTempText

NormalExit:
    Exit Function

Errorhandler:
    Resume Next

End Function

其他功能

'* +++++++++++++++++++++++++++++++++++++++
'功能简介:可以对指定长度的段落进行删除,当LEN=1时可对空白段落进行删除。
Sub DelBlank() 
    Dim i As Paragraph, n As Long 
    Application.ScreenUpdating = False '关闭屏幕刷新 
    For Each i In ActiveDocument.Paragraphs '在活动文档的段落集合中循环 
        If Len(i.Range) = 1 Then '判断段落长段,此处可根据文档实际情况 
            i.Range.Delete '进行必要的修改可将任意长度段落删除 
            n = n + 1 '计数 
        End If 
    Next 
    MsgBox "共删除空白段落" & n & "个!" 
    Application.ScreenUpdating = True '恢复屏幕刷新 
End Sub



'* +++++++++++++++++++++++++++++++++++++++
'以指定字符重新划分段落并插入时间序列数
'^The Code CopyIn [ThisDocument-ThisDocument]^'
'* --------------------------------------------------------------------------
Sub CreateParagraph() 
    Dim I As Long, N As Integer 
    On Error Resume Next '忽略错误 
    Application.ScreenUpdating = False '关闭屏幕更新 
    With ActiveDocument 
        '将文档中所有段落标记删除 
        .Content.Find.Execute FindText:="^p", ReplaceWith:="", Replace:=wdReplaceAll 
        For I = 0 To .Content.End Step 10 '以10个字符位置(包括非打印字符)为步长循环 
            '每段十个字符部分分成段落(注意插入的段落标记也是一个字符) 
            .Range(I, I + 10 + N).InsertAfter Chr(13) 
            N = N + 1 '计算插处的段落标记个数 
        Next 
    End With 
    Application.ScreenUpdating = True '恢复屏幕更新 
    InsertTimer 
End Sub 
'---------------------- 
Sub InsertTimer() 
    Dim I As Paragraph, N As Integer, TimeStr As String 
    On Error Resume Next '忽略错误 
    Application.ScreenUpdating = False '关闭屏幕更新
    For Each I In ActiveDocument.Paragraphs '在文档新的段落中循环 
        If N < 10 Then '<10,TimeStr的分钟值为5(保持两位数05) 
            TimeStr = "[00:0" & N & ".00]" 
        ElseIf N = 60 Then 'N=60时时间数进一并保持该数据(不再向上) 
            TimeStr = "[01:00.00]" N = 0 
        Else 'TimeStr的分钟数照计(两位数) 
            TimeStr = "[00:" & N & ".00]" 
        End If 
            I.Range.InsertBefore TimeStr '每个段前插入时间数值 
            N = N + 5 '以5为步长累加 
    Next 
    Application.ScreenUpdating = True '恢复屏幕更新 
End Sub '---------------------


'* +++++++++++++++++++++++++++++++++++++++
'四) 段落样式与格式的应用
'功能简介:由于手动录入的段落编号不能被WORD所识别,为以后的样式与格式的设置以及目录索引等带来一系列的问题,本代码即是将其转换为指定样式的过程.

'^The Code CopyIn [ThisDocument-ThisDocument]^'
'* --------------------------------------------------------------------------
Sub Sample()
    Dim i As Paragraph, MyStr As String 
    Application.ScreenUpdating = False 
    MyStr = "一二三四五六七八九十" '假定为手动加注每个段落开头为中文大写数字 
    For Each i In Me.Paragraphs 
        If i.Range Like "(#)*" = True Then 
            i.Style = wdStyleHeading9 '标题9是以(1)等开头的数字 
        ElseIf i.Range Like "#.#.#.#*" = True Then 
            i.Style = wdStyleHeading8 '标题8是以1.1.1.1的形式开头的段落 
        ElseIf i.Range Like "#.#.#*" = True Then 
            i.Style = wdStyleHeading7 '标题7是以1.1.1的形式开头的段落 
        ElseIf i.Range Like "#.#*" = True Then 
            i.Style = wdStyleHeading6 '标题6是以1.1形式开头的段落 
        ElseIf InStr(MyStr, Me.Range(i.Range.Start, i.Range.Start + 1).Text) > 0 Then 
            i.Style = wdStyleHeading5 '标题5是以一等形式开头的段落 
        Else 
            i.Style = wdStyleNormal '其它为正文样式 
        End If 
    Next 
    Application.ScreenUpdating = True
End Sub


'五) 根据预定义段落进行段落样式的设置和插入目录
'* +++++++++++++++++++++++++++++++++++++++
'^The Code CopyIn [ThisDocument-ThisDocument]^'
'* --------------------------------------------------------------------------
'功能简介:对于网上复制的一些非正规编排的文档,没有大纲级别,也没有很好地样式格式以区分,
'利用此功能,可以根据先前的手动目录,更改为自动生成的目录,便于文档管理。
Sub Contents() 
    Dim I As Paragraph, N As Byte, A As Byte, B As Byte, X As Long, DelRange As Range 
    Application.ScreenUpdating = False 
    A = 2 
    B = 13 
    With ActiveDocument 
        For Each I In .Paragraphs '在段落中循环 X = X + 1 '计数 
            For N = A To B '进入文档第二段落到第十三段落间的循环 
                If X > B Then 
                    If I.Range = .Paragraphs(N).Range Then 
                        I.Style = .Styles(wdStyleHeading1) '将 A = A + 1 '累计 
                    End If 
                End If 
            Next 
        Next
        Set DelRange = Range(.Paragraphs(2).Range.Start, .Paragraphs(13).Range.End) 
            DelRange.Delete '删除原文档的第二~第十三个段落 
            .Paragraphs(2).Range.Select '插入/引用/索引与目录 
            .TablesOfContents.Add Range:=Selection.Range, RightAlignPageNumbers:= _ True, UseHeadingStyles:=True, UpperHeadingLevel:=1, _ LowerHeadingLevel:=3, IncludePageNumbers:=True, AddedStyles:="", _ UseHyperlinks:=True, HidePageNumbersInWeb:=True
        .TablesOfContents(1).TabLeader = wdTabLeaderDots 
        .TablesOfContents.Format = wdIndexIndent 
    End With 
    Application.ScreenUpdating = True 
End Sub


'九) 查找与替换的基本代码用法之一
'* +++++++++++++++++++++++++++++++++++++++
'^The Code CopyIn [ThisDocument-ThisDocument]^'
'* --------------------------------------------------------------------------
Sub Example() 
    With ActiveDocument.Content.Find 
        .ClearFormatting '清除格式设置 
        .Font.Name = "华文细黑" '查找的字体格式 
        With .Replacement '替换条件 
            .ClearFormatting '清除格式设置 
            .Font.Name = "黑体" '替换成黑体 
        End With 
        .Execute FindText:="", ReplaceWith:="", Format:=True, _ Replace:=wdReplaceAll '是格式替换,全部替换 
    End With 
End Sub 
'----------------------


十一) 查找与替换的基本代码用法之三(批量替换)
功能简介:同时进行多个查找与替换,支持非通配符下的特殊字符的替换。
比如,适用于ISO文件,因组织机构调整,对所有原有部门一次输入后替换为新部门。
查找的各个内容之间,用英文逗号分隔(","),查找数量不限。
替换的各个内容之间,用英文逗号分隔(","),替换数量必须等同于查找数量,如是删除某个查找内容,替换中键入""(空空)
'* +++++++++++++++++++++++++++++ '^The Code CopyIn [ThisDocument-ThisDocument]^' '* -----------------------------
Private Sub Document_Close() 
    On Error Resume Next 
    Application.CommandBars("Edit").Controls("多个替换").Delete '恢复原有菜单 
End Sub 
'---------------------- 
Private Sub Document_Open() 
    On Error Resume Next 
    Dim NewButton As CommandBarButton 
    CustomizationContext = ActiveDocument '将自定义组合键和工具命令保存于活动文档中 
    '指定CTRL+F为键盘快捷方式 
    KeyBindings.Add wdKeyCategoryMacro, "MySub", BuildKeyCode(wdKeyControl, wdKeyF) 
    '指定F5为快捷方式 
    KeyBindings.Add wdKeyCategoryMacro, "MySub", BuildKeyCode(wdKeyF5) 
    Application.CommandBars("Edit").Controls("多个替换").Delete 
    '预防性删除 
    Set NewButton = Application.CommandBars("Edit").Controls.Add(Type:=msoControlButton, Before:=11) 
    With NewButton 
        .Caption = "多个替换" '命令名称 
        .FaceId = 100 '命令的FaceId 
        .Visible = True '可见 
        .OnAction = "MySub" '指定响应过程名 
    End With 
End Sub '---------------------- 
Sub MySub() 
    UserForm1.Show 
End Sub '---------------------- 
Sub ComReset() 
'恢复默认设置
    Application.CommandBars("Edit").Reset 
End Sub



' 十二) 查找与替换的基本代码用法之四-全文件夹替换
' 功能简介:批量多文件(全文件夹)的多文本一次性替换操作。
' 运行本程序后,先输入需查找和与之对应的替换的文本,然后点击“选择文件夹”,
' 您可以找到指定的文件夹中的部分或者所有文件,注意,您需要全选文件(CTRL+A),
' 或者使用SHIFT/CTRL配合鼠标键选取多个文件),确定后自动进行批量替换。
'* +++++++++++++++++++++++++++++ '^The Code CopyIn [ThisDocument-ThisDocument]^' '* -----------------------------
Private Sub Document_Open() 
    Application.Windows(ThisDocument.Name).Visible = False 
    MySub 
End Sub '---------------------- 
Sub MySub() 
    UserForm1.Show 
End Sub
 '---------------------- 
 '* +++++++++++++++++++++++++++++ 
 '^The Code CopyIn [用户窗体-UserForm1]^' '* -----------------------------
Private Sub CommandButton1_Click() 
    Me.TextBox1 = "" 
    Me.TextBox2 = "" 
    Me.TextBox1.SetFocus 
End Sub '---------------------- 
Private Sub CommandButton2_Click() 
    Dim MyFind() As String, MyRep() As String, i As Integer, aStory As Variant 
    Dim MyDialog As FileDialog, vrtSelectdeItem As Variant, Doc As Document 
    On Error Resume Next '检查是否为空 
    MsgBox "请先正确录入查找与对应替换的内容,以英文逗号分隔" & vbCrLf & _ "在选定文件夹中,您可以全选或部分选定文件(CTRL/SHIFT)+鼠标单击", vbInformation
    If Me.TextBox1 = "" And Me.TextBox2 = "" Then Exit Sub 
    MyFind = Split(Me.TextBox1, ",") 
    MyRep = Split(Me.TextBox2, ",") 
    If UBound(MyRep) <> UBound(MyFind) Then 
        '如果两个文本框的分隔数目不一致,提示 
        MsgBox "替换的数目与查找数目不一致!", vbExclamation + vbOKOnly, "Warnning" 
        Me.TextBox2.SetFocus 
        Exit Sub 
    End If '定义一个文件夹选取对话框 
    Set MyDialog = Application.FileDialog(msoFileDialogFilePicker) 
    With MyDialog 
        .Filters.Clear '清除所有文件筛选器中的项目 
        .Filters.Add "所有 WORD 文件", "*.doc", 1 '增加筛选器的项目为所有WORD文件 
        .AllowMultiSelect = True '允许多项选择 
        If .Show = -1 Then '确定 
            Application.ScreenUpdating = False 
            For Each vrtselecteditem In .SelectedItems '在所有选取项目中循环 
                Set Doc = Documents.Open(FileName:=vrtselecteditem, Visible:=False) '定义两个数组,以","分隔 
                With Doc 
                For i = 0 To UBound(MyFind) '一个从下标为0的循环替换 
                    For Each aStory In .StoryRanges '在文档的各个文字部分 '如果是"",则相当于删除原查找内容 
                        aStory.Find.Execute findtext:=MyFind(i), _ replacewith:=VBA.IIf(MyRep(i) = """""", "", MyRep(i)), Replace:=2 '如果有下一节中相同内容文字部分,也进行替换 
                        If Not aStory.NextStoryRange Is Nothing Then _ aStory.NextStoryRange.Find.Execute findtext:=MyFind(i), _ replacewith:=VBA.IIf(MyRep(i) = """""", "", MyRep(i)), Replace:=2 
                    Next 
                Next 
                Doc.Close True 
                End With 
            Next vrtselecteditem 
        End If 
    End With 
    Application.ScreenUpdating = True 
    Unload Me '卸载窗体 
End Sub '---------------------- 
Private Sub UserForm_Initialize()
    Me.Caption = "多文本替换操作" 
    Me.TextBox1.SetFocus 
    Me.CommandButton2.Default = True 
End Sub '---------------------- 
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) 
    ThisDocument.Close False 
End Sub '----------------------


' 四十一) 后台解除已知密码的VBA工程的代码
' 功能简介:用于后台解除VBA工程代码并完成相应修改的代码,亦可用于EXCEL中
'* +++++++++++++++++++++++++++++++++++++++
'^The Code CopyIn [ThisDocument-ThisDocument]^'
'* --------------------------------------------------------------------------
Sub UnProtectPassWord() 
    Dim MyPw As String '最新修改时间:2004-12-11 16:15:04 
    MyPw = "123" '假设密码为123,可修改 
    Application.ScreenUpdating = False '打开VBE/工具/Project属性对话框 
    Application.VBE.CommandBars.FindControl(ID:=2578).Execute '发送密码和回车,第二次回车为确定属性对话框框 
    SendKeys MyPw & "{Enter 2}", True 
    Call ReWork 
    Application.ScreenUpdating = True
End Sub '----------------------
Sub ReWork()
'测试用于修改VBA代码的代码,注意宏安全性的可靠性来源中勾选信 
'任对于VB项目的访问 
    Me.VBProject.VBComponents(1).CodeModule.ReplaceLine 3, "'最新修改时间:" & Now'将当前时间写在代码中 
End Sub '----------------------


' 五十) 批量重命名文件
'* +++++++++++++++++++++++++++++++++++++++
'^The Code CopyIn [ThisDocument-ThisDocument]^'
'* --------------------------------------------------------------------------
Sub FileNewName() 
    Dim FSO As Object, FDR As Object, F As Object, i As Variant, OldName As String, NewName As String 
    On Error Resume Next '忽略错误 
    Set FSO = CreateObject("Scripting.FileSystemObject") '创建计算机文件系统以向其访问 
    Set FDR = FSO.GetFolder("D:\Test") '指定其中访问的文件夹对象 
    Set F = FDR.Files '定义该文件夹中的所有文件集合 
    For Each i In F '在指定文件下的文件中循环 
        OldName = FDR & "\" & i.Name NewName = FDR & "\" & Mid(i.Name, 3) '去掉前两个字符 
        Name OldName As NewName 
    Next i 
End Sub '----------------------




' 设置字体的格式,下例将活动文档首段的格式设置为 24 磅Arial 和倾斜
Set myRange = ActiveDocument.Paragraphs(1).Range
With myRange.Font
.Bold = True
.Name = "Arial"
.Size = 24
End With


' 下例将活动文档中标题 2 的样式更改为 Arial 和加粗
With ActiveDocument.Styles(wdStyleHeading2).Font
.Name = "Arial"
.Italic = True
End With

' 关键字“New”来创建一个独立应用的新 Font 对象。然后将该 Font 对象应用于活动文档的首段
Set myFont = New Font
myFont.Bold = True
myFont.Name = "Arial"
ActiveDocument.Paragraphs(1).Range.Font = myFont

' 通过使用 ParagraphFormat 对象可以设置文本中段落的格式。将活动文档第三段居中对齐
ActiveDocument.Paragraphs(3).Format.Alignment = _WdAlignParagraphCenter
' 定段落的段前距离设置为12 磅
Selection.FormatParagraph.SpaceBefore = 12

' 应用于活动文档的第一个段落
Dim myParaF As New ParagraphFormat
myParaF.Alignment = wdAlignParagraphCenter
myParaF.Borders.Enable = True
ActiveDocument.Paragraphs(1).Format = 




'------------------------PPT-------------------------------------------
'vba如何给每张PPT批量插入一张(各种格式无固定命名的)图片,且确保图片大小是一样的

作者:Emrys
链接:https://www.zhihu.com/question/547915281/answer/2655781983
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

代码中的 numPicturePerSlide 的值需要根据实际需要进行调整,这里默认设置为 3, 即每页 PPT 插入 3 张图片。Sub InsertPicturesToPPT()
  Dim sld As Slide
  Dim shp As Shape
  Dim i, count, numPicturePerSlide As Long
  Dim slideWidth, slideHeight As Single

  '用这个变量设置每页 PPT 要插入的图片数量
  numPicturePerSlide = 3

  fd = Split(FileDialogOpen, vbLf)
  If Left(fd(0), 1) = "-" Then
    Debug.Print "Canceled"
    Exit Sub
  End If

  slideWidth = ActivePresentation.PageSetup.SlideWidth
  slideHeight = ActivePresentation.PageSetup.SlideHeight

  count = 0
  For Each sld In ActivePresentation.Slides
    ' 跳过隐藏的 PPT 页
    If sld.SlideShowTransition.Hidden = msoFalse Then
      If count + LBound(fd) > UBound(fd) Then
        ' No picture to insert
        Exit For
      End If

      For i = 1 To numPicturePerSlide
        If count + LBound(fd) <= UBound(fd) Then
          Set shp = sld.Shapes.AddPicture( _
            FileName:=fd(count + LBound(fd)), _
            LinkToFile:=msoFalse, _
            SaveWithDocument:=msoTrue, _
            Left:=0, _
            Top:=0, _
            Width:=-1, _
            Height:=-1 _
          )
          With shp
            .LockAspectRatio = msoTrue  ' 锁定纵横比
            '.ScaleHeight 0.75, msoTrue
            .Left = slideWidth / numPicturePerSlide * i - .Width / 2
            .Top = (slideHeight - .Height) / 2
            '.ZOrder msoSendToBack   ' 将图片设置为最底层
          End With
          count = count + 1
        Else
          Exit For
        End If
      Next i
    End If
  Next sld

  'MsgBox "Processing finished. Inserted (" & count & ") pictures in total"
  MsgBox "插入图片完成,共插入 " & count & " 张图片"

End Sub

Function FileDialogOpen() As String

  #If Mac Then
    ' 默认路径
    mypath = MacScript("return (path to desktop folder) as String")

    sMacScript = "set applescript's text item delimiters to "","" " & vbNewLine & _
    "try " & vbNewLine & _
    "set theFiles to (choose file of type {""png"", ""jpg"", ""jpeg"", ""svg"", ""tiff"", ""gif""}" & _
    "with prompt ""请选择一个或多个要插入的图片"" default location alias """ & _
    mypath & """ multiple selections allowed true)" & vbNewLine & _
    "set applescript's text item delimiters to """" " & vbNewLine & _
    "on error errStr number errorNumber" & vbNewLine & _
    "return errorNumber " & vbNewLine & _
    "end try " & vbNewLine & _
    "repeat with i from 1 to length of theFiles" & vbNewLine & _
    "if i = 1 then" & vbNewLine & _
    "set fpath to POSIX path of item i of theFiles" & vbNewLine & _
    "else" & vbNewLine & _
    "set fpath to fpath & """ & vbNewLine & _
    """ & POSIX path of item i of theFiles" & vbNewLine & _
    "end if" & vbNewLine & _
    "end repeat" & vbNewLine & _
    "return fpath"

    FileDialogOpen = MacScript(sMacScript)

  #Else
    With Application.FileDialog(msoFileDialogOpen)
      .AllowMultiSelect = True
      .Title = "请选择要一个或多个要插入的图片"
      .Filters.Add "图片", "*.png; *.jpg; *.jpeg; *.svg; *.tiff; *.gif", 1
      If .Show = -1 Then
        FileDialogOpen = ""
        For i = 1 To .SelectedItems.Count
          If i = 1 Then
            FileDialogOpen = .SelectedItems.Item(i)
          Else
            FileDialogOpen = FileDialogOpen & vbLf & .SelectedItems.Item(i)
          End If
        Next
      Else
        FileDialogOpen = "-"
      End If
    End With

  #End If
End Function

'上述代码插入的图片没有进行统一的位置和大小调整,如果需要进行调整,可以在插入完成之后,再使用下列回答中的方法解决:

'选中的那些形状会被作为参考,之后其他页中与它们类型相同且距离最近的形状,会被设置为与之相同的位置和大小
作者:Emrys
链接:https://www.zhihu.com/question/546616706/answer/2607870575
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Sub AlignToSelectedShapes()
    Dim sld As Slide
    Dim slideIndex As Long
    Dim shp, selectedShp, closestShp As Shape
    Dim distance, minDistance, MAX_DIST As Double
    Dim count As Long

    MAX_DIST = 9E+307
    If ActiveWindow.Selection.Type = ppSelectionShapes Then
        Dim num As Long
        Dim shapeIDs() As Long
        num = ActiveWindow.Selection.ShapeRange.Count
        ReDim shapeIDs(num)

        count = 0
        slideIndex = ActiveWindow.Selection.SlideRange.SlideIndex
        For Each sld In ActivePresentation.Slides
            If sld.SlideIndex <> slideIndex Then
                ' 清空 shapeIDs 数组
                For i = 1 To num
                    shapeIDs(i) = -1
                Next i

                num = 0
                For Each selectedShp In ActiveWindow.Selection.ShapeRange
                    num = num + 1
                    minDistance = MAX_DIST
                    For Each shp In sld.Shapes
                        If shp.Type = selectedShp.Type And Not IsInArray(shp.Id, shapeIDs) Then
                            distance = GetDistance(shp, selectedShp)
                            If distance < minDistance Then
                                minDistance = distance
                                Set closestShp = shp
                            End If
                        End If
                    Next shp

                    If minDistance < MAX_DIST Then
                        ' 找到了最近的未经处理的形状
                        shapeIDs(num) = closestShp.Id
                        ProcessOneShape closestShp, selectedShp.Left, selectedShp.Top, selectedShp.Width, selectedShp.Height
                    End If
                    count = count + 1
                Next selectedShp
            End If
        Next sld
        MsgBox "共对齐了" & count & "个形状。"
    Else
        MsgBox "未发现任何选中的形状", vbExclamation, "No Shape Found"
    End If
End Sub


Function ProcessOneShape(oSh As Shape, left As Single, top As Single, width As Single, Height As Single)
    Dim lockAspectRatio As Boolean

    oSh.Left = left
    oSh.Top = top

    lockAspectRatio = oSh.LockAspectRatio
    oSh.LockAspectRatio = msoFalse
    oSh.Width = width
    oSh.Height = height
    oSh.LockAspectRatio = lockAspectRatio
End Function


Function GetDistance(ByVal oSh1 As Shape, ByVal oSh2 As Shape) As Double
    Dim distX, distY As Double

    centerX1 = oSh1.Left + oSh1.Width * 0.5
    centerX2 = oSh2.Left + oSh2.Width * 0.5
    centerY1 = oSh1.Top + oSh1.Height * 0.5
    centerY2 = oSh2.Top + oSh2.Height * 0.5

    distX = centerX1 - centerX2
    distY = centerY1 - centerY2

    GetDistance = Sqr(distX * distX + distY * distY)
End Function


'https://wellsr.com/vba/2016/excel/check-if-value-is-in-array-vba/
Private Function IsInArray(valToBeFound As Long, arr() As Long) As Boolean
Dim element As Variant
On Error GoTo IsInArrayError: 'array is empty
    For Each element In arr
        If element = valToBeFound Then
            IsInArray = True
            Exit Function
        End If
    Next element
Exit Function
IsInArrayError:
On Error GoTo 0
IsInArray = False
End Function
'选中的那些形状会被作为参考,之后其他页中与它们名字相同且类型相同的形状,会被设置为与之相同的位置、大小、格式
' 【注意】:这里的名字是指选中某个形状后,在「选择窗格」的形状列表中对应被选中项的名字。

作者:Emrys
链接:https://www.zhihu.com/question/442816732/answer/1790328897
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Sub AlignToSelectedShape()
    Dim sld As Slide
    Dim shp, selectedShp As Shape
    Dim slideIndex As Long
    Dim count As Long

    If ActiveWindow.Selection.Type = ppSelectionShapes Or ActiveWindow.Selection.Type = ppSelectionText Then
        ' A shape is selected or a textbox is focused (text is selected)
        count = 0
        slideIndex = ActiveWindow.Selection.SlideRange.SlideIndex
        For Each selectedShp In ActiveWindow.Selection.ShapeRange
            For Each sld In ActivePresentation.Slides
                If sld.SlideIndex <> slideIndex Then
                    For Each shp In sld.Shapes
                        If shp.Type = selectedShp.Type And shp.Name = selectedShp.Name Then
                            shp.Left = selectedShp.Left
                            shp.Top = selectedShp.Top
                            shp.Width = selectedShp.Width
                            shp.Height = selectedShp.Height
                            ' Copy format from the selected shape
                            selectedShp.PickUp
                            shp.Apply
                            count = count + 1
                        End If
                    Next shp
                End If
            Next sld
        Next selectedShp
        MsgBox "共对齐了" & count & "个形状。"
    Else
        MsgBox "未发现任何选中的形状或文本框", vbExclamation, "No Shape Found"
    End If
End Sub


'ppt插入参考文献

' 注:需要事先将每一页中对应参考文献的文本框名称统一改为 tb_ref
' (或者其他名字也可以,在下面代码中由 tb_name 变量定义),才能使用下面的代码自动进行处理。

作者:Emrys
链接:https://www.zhihu.com/question/35443903/answer/2672495862
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Sub CollectAllRefs()
    Dim i, j, p, num_slides, count, slide_id As Long
    Dim oSld As Slide
    Dim shp As Shape
    Dim flag As Boolean
    Dim tb_name, tb_text, ret, slide_name As String
    Dim to_write() As String
    Dim tmp As String
    Dim ref_pages() As String
    Dim ref_p() As String

    'tb_name = InputBox("Please enter the name of textboxes that contain references", "Processing references", "tb_ref")
    tb_name = InputBox("请输入含有参考文献的文本框名称", "批量整理参考文献", "tb_ref")
    If StrPtr(tb_name) = 0 Then
        ' User cancels
        Exit Sub
    End If

    ReDim Preserve to_write(0 To 0)
    ReDim Preserve ref_pages(0 To 0)

    num_slides = ActivePresentation.Slides.Count
    For i = 1 To num_slides
        Set oSld = ActivePresentation.Slides(i)

        ' Skip hidden slides
        If oSld.SlideShowTransition.Hidden = msoFalse Then
            For Each oShp In oSld.Shapes
                ' Check to see if shape has a text frame and text
                If oShp.Name = tb_name And oShp.HasTextFrame And oShp.TextFrame.HasText Then
                    For p = 1 To oShp.TextFrame.TextRange.Paragraphs.Count
                        tb_text = oShp.TextFrame.TextRange.Paragraphs(p).Text
                        tb_text = Replace(tb_text, vbCrLf, "")
                        tb_text = Replace(tb_text, vbCr, "")
                        tb_text = Replace(tb_text, vbLf, "")
                        tb_text = Replace(tb_text, vbNewLine, "")
                        If Trim(tb_text & vbNullString) <> vbNullString Then
                            ' Not an empty string
                            ret = ProcessOneString(tb_text, to_write)

                            If Left(ret, 1) <> "*" Then
                                ' Add a new reference
                                ReDim Preserve to_write(0 To (UBound(to_write, 1) + 1))
                                j = UBound(to_write, 1)
                                to_write(j) = ret
                                ReDim Preserve ref_pages(0 To (UBound(ref_pages, 1) + 1))
                                ref_pages(UBound(ref_pages, 1)) = CStr(i)
                            Else
                                ' Found an existing reference
                                j = CLng(Mid(ret, 2, Len(ret)))
                                ret = to_write(j)
                                ref_pages(j) = ref_pages(j) & "," & CStr(i)
                            End If

                            ' Modify the numbering in each slide
                            count= InStr(1, oShp.TextFrame.TextRange.Paragraphs(p).Text, ret, vbTextCompare)
                            If count = 0 Then
                                ' This should not happen for normal cases
                                Debug.Print tb_text & vbNewLine & ret & vbNewLine & "==========" & vbNewLine
                            End If
                            With oShp.TextFrame.TextRange.Paragraphs(p)
                                .Characters(1, count - 1) = ""
                                .InsertBefore("[" & j - LBound(to_write) & "] ")
                            End With
                        End If
                    Next p
                End If
            Next oShp
        End If
    Next i

    Set oSld = ActivePresentation.Slides.Add(Index:=ActivePresentation.Slides.count + 1, Layout:=ppLayoutBlank)
    With oSld.Shapes.AddTextbox( _
        Orientation:=msoTextOrientationHorizontal, _
        Left:=ActivePresentation.PageSetup.SlideWidth * 0.1, _
        Top:=ActivePresentation.PageSetup.SlideHeight * 0.1, _
        Width:=ActivePresentation.PageSetup.SlideWidth * 0.8, _
        Height:=ActivePresentation.PageSetup.SlideHeight * 0.8 _
    ).TextFrame
        count = 0
        For i = LBound(to_write) To UBound(to_write)
            If Trim(to_write(i) & vbNullString) <> vbNullString Then
                count = count + 1
                tmp = "[" & count & "] " & to_write(i) & " "
                With .TextRange.InsertAfter(tmp)
                    .Font.Superscript = msoFalse
                End With

                ' Add link to pages that refer to the references
                ref_p = Split(ref_pages(i), ",")
                flag = msoFalse
                For j = LBound(ref_p) To UBound(ref_p)
                    If Trim(ref_p(j) & vbNullString) <> vbNullString Then
                        If flag Then
                            With .TextRange.InsertAfter(", ")
                                .Font.Superscript = msoTrue
                            End With
                        End If
                        With .TextRange.InsertAfter(ref_p(j))
                            slide_id = ActivePresentation.Slides(CLng(ref_p(j))).SlideID
                            slide_name = ActivePresentation.Slides(CLng(ref_p(j))).Name
                            .ActionSettings(1).Hyperlink.SubAddress = slide_id & "," & ref_p(j) & "," & slide_name
                            .Font.Superscript = msoTrue
                        End With
                        flag = msoTrue
                    End If
                Next j
                If i < UBound(to_write) Then
                    With .TextRange.InsertAfter(vbNewLine)
                        .Font.Superscript = msoFalse
                    End With
                End If
            End If
        Next i
        .AutoSize = ppAutoSizeShapeToFitText
    End With

    If count > 0 Then
        'MsgBox "Added " & count & " references at the end"
        MsgBox "已在尾页添加 " & count & " 条参考文献"
    Else
        oSld.Delete
        'MsgBox "No reference is found"
        MsgBox "未找到参考文献"
    End If
End Sub


Function ProcessOneString(in_text As Variant, all_text As Variant) As String
    Dim j As Long
    Dim found_match As Boolean
    Dim record As String

    Dim strPattern As String
    #If Mac Then
        sMacScript = "set s to """ & in_text & """" & vbNewLine & _
        "set srpt to ""echo \"""" & s & ""\"" | sed -r \""s/^([0-9]+([[:space:]]|\\.)|[[【][0-9]+[]】]|\\*)[[:space:]]*//\""""" & vbNewLine & _
        "return (do shell script srpt)"

        Debug.Print sMacScript
        in_text = MacScript(sMacScript)
    #Else
        strPattern = "^([0-9]+[\s\.]|[\[【][0-9]+[\]】]|\*)\s*"
        Set regEx = CreateObject("VBScript.RegExp")
        With regEx
            .Global = True
            .MultiLine = False
            .IgnoreCase = True
            .Pattern = strPattern
        End With

        If regEx.TEST(in_text) Then
            in_text = regEx.Replace(in_text, "")
        End If
    #End If

    found_match = msoFalse
    For j = LBound(all_text) To UBound(all_text)
        record = CStr(all_text(j))
        If Trim(record & vbNullString) <> vbNullString Then
            If InStr(1, record, in_text, vbTextCompare) > 0 Then
                found_match = msoTrue
                ProcessOneString = "*" & CStr(j)
                Exit For
            End If
        End If
    Next j
    If found_match = msoFalse Then
        ProcessOneString = in_text
    End If

End Function


'ppt删除备注
Sub RemoveAllSpeakerNotes()
    Dim sld As Slide
    For Each sld In ActivePresentation.Slides
        sld.NotesPage.Shapes.Placeholders(2).TextFrame.TextRange = ""
    Next sld
End Sub


' 如果不想要导出全部幻灯片的备注,可以在代码里面修改页码范围,即把下面的代码
' For i = 1 To num_slides修改成你想要的范围(如第 4 页 到第 8 页):For i = 4 To 8Sub ExportNote()
Sub ExportText()
  Dim oPres As Presentation
  Dim oSlides As Slides
  Dim oSld As Slide         'Slide Object
  Dim oShp As Shape         'Shape Object
  Dim iFile As Integer      'File handle for output
  iFile = FreeFile          'Get a free file number
  Dim PathSep As String
  Dim path As String
  Dim FileNum As Integer
  Dim sTempString As String

  Set oPres = ActivePresentation
  Set oSlides = oPres.Slides
  filename = oPres.FullName

  #If Mac Then
    PathSep = "/"
    path = MacScript("return POSIX path of (path to desktop folder)")
    if Right(path, 1) = PathSep And Len(path) > 1 Then
        path = Mid(path, 1, Len(path) - 1)
    End If
  #Else
    PathSep = "\"
    path = oPres.Path
  #End If

  FileNum = FreeFile

  'Open output file
  ' NOTE:  errors here if file hasn't been saved
  Open path & PathSep & filename & ".txt" For Output As FileNum

  On Error GoTo ErrorHandler   ' Enable error-handling routine.

  num_slides = ActivePresentation.Slides.Count

  For i = 1 To num_slides
    Set oSld = ActivePresentation.Slides(i)
    Print #iFile, "(Page " & CStr(oSld.SlideNumber) & ")" & vbNewLine

    Print #iFile, oSld.NotesPage.Shapes.Placeholders(2).TextFrame.TextRange

    Print #iFile, "--------------------------" & vbNewLine & vbNewLine & vbNewLine
    Next i
  Close #iFile

  MsgBox "文件已创建在'" & path & PathSep & filename & ".txt'"

  Exit Sub       ' Exit to avoid handler.
  ErrorHandler:  ' Error-handling routine.
    Print #iFile, "(Error)" & vbNewLine
    Resume Next  ' Resume execution at the statement immediately
                 ' following the statement where the error occurred.
End Sub




' ' Windows 上从单页或多页 PPT 中提取所有文本框内的文字


' 作者:Emrys
' 链接:https://www.zhihu.com/question/387555935/answer/1160380698
' 来源:知乎
' 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

' 运行之后,就会在 PPT 同目录下生成与 PTT 文件同名的 .txt 文件,其中内容格式如下:Slide: [页码编号][这一页第1个形状的名称]: [文本内容][这一页第2个形状的名称]: [文本内容]Slide: [页码编号][这一页第1个形状的名称]: [文本内容]……<img src="https://pic4.zhimg.com/v2-b21f804fae7fb6313caac4e29e094293_b.jpg" data-size="normal" data-rawwidth="1497" data-rawheight="877" data-default-watermark-src="https://pic1.zhimg.com/v2-8693b062705e0c7c6b9a77165d6f20e8_b.jpg" class="origin_image zh-lightbox-thumb" width="1497" data-original="https://pic4.zhimg.com/v2-b21f804fae7fb6313caac4e29e094293_r.jpg"/>导出文本的格式上面用到的 VBA 代码如下(也适用于 Mac):如果不想要导出全部幻灯片的文本,可以在代码里面修改页码范围,即把下面的代码For i = 1 To num_slides修改成你想要的范围(如第 4 页 到第 8 页):For i = 4 To 8Sub ExportText()
  Dim oPres As Presentation
  Dim oSlides As Slides
  Dim oSld As Slide         'Slide Object
  Dim oShp As Shape         'Shape Object
  Dim iFile As Integer      'File handle for output
  iFile = FreeFile          'Get a free file number
  Dim PathSep As String
  Dim FileNum As Integer
  Dim sTempString As String

  #If Mac Then
    PathSep = "/"
  #Else
    PathSep = "\"
  #End If

  Set oPres = ActivePresentation
  Set oSlides = oPres.Slides

  FileNum = FreeFile

  'Open output file
  ' NOTE:  errors here if file hasn't been saved
  'Open oPres.Path & PathSep & "AllText.txt" For Output As FileNum
  Open oPres.Path & PathSep & oPres.Name & ".txt" For Output As FileNum
  
  num_slides = ActivePresentation.Slides.Count

  For i = 1 To num_slides
    Set oSld = ActivePresentation.Slides(i)
    Print #iFile, "Slide:" & vbTab & CStr(oSld.SlideNumber)

    For Each oShp In oSld.Shapes
      'Check to see if shape has a text frame and text
      If oShp.HasTextFrame And oShp.TextFrame.HasText Then
        If oShp.Type = msoPlaceholder Then
            Select Case oShp.PlaceholderFormat.Type
                Case Is = ppPlaceholderTitle, ppPlaceholderCenterTitle
                    Print #iFile, "标题:" & vbTab & oShp.TextFrame.TextRange
                Case Is = ppPlaceholderBody
                    Print #iFile, "正文:" & vbTab & oShp.TextFrame.TextRange
                Case Is = ppPlaceholderSubtitle
                    Print #iFile, "副标题:" & vbTab & oShp.TextFrame.TextRange
                Case Else
                    Print #iFile, "其他占位符:" & vbTab & oShp.TextFrame.TextRange
            End Select
        Else
            Print #iFile, vbTab & oShp.TextFrame.TextRange
        End If  ' msoPlaceholder
      Else  ' it doesn't have a textframe - it might be a group that contains text so:
        If oShp.Type = msoGroup Then
            sTempString = TextFromGroupShape(oShp)
            If Len(sTempString) > 0 Then
                Print #iFile, sTempString
            End If
        End If
      End If    ' Has text frame/Has text
    Next oShp
    
    Print #iFile, vbCrLf
    Next i
  Close #iFile

  'MsgBox "文件已创建在 '" & oPres.Path & PathSep & "AllText.txt'"
  MsgBox "文件已创建在 '" & oPres.Path & PathSep & oPres.Name & ".txt'"
End Sub

Function TextFromGroupShape(oSh As Shape) As String
' Returns the text from the shapes in a group
' and recursively, text within shapes within groups within groups etc.

    Dim oGpSh As Shape
    Dim sTempText As String

    If oSh.Type = msoGroup Then
        For Each oGpSh In oSh.GroupItems
            With oGpSh
                If .Type = msoGroup Then
                    sTempText = sTempText & TextFromGroupShape(oGpSh)
                Else
                    If .HasTextFrame Then
                        If .TextFrame.HasText Then
                            sTempText = sTempText & "(Gp:) " & .TextFrame.TextRange.Text & vbCrLf
                        End If
                    End If
                End If
            End With
        Next
    End If

    TextFromGroupShape = sTempText

NormalExit:
    Exit Function

Errorhandler:
    Resume Next

End Function

ppt每页插图



'------------------------PPT-------------------------------------------
'vba如何给每张PPT批量插入一张(各种格式无固定命名的)图片,且确保图片大小是一样的

作者:Emrys
链接:https://www.zhihu.com/question/547915281/answer/2655781983
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

代码中的 numPicturePerSlide 的值需要根据实际需要进行调整,这里默认设置为 3, 即每页 PPT 插入 3 张图片。Sub InsertPicturesToPPT()
  Dim sld As Slide
  Dim shp As Shape
  Dim i, count, numPicturePerSlide As Long
  Dim slideWidth, slideHeight As Single

  '用这个变量设置每页 PPT 要插入的图片数量
  numPicturePerSlide = 3

  fd = Split(FileDialogOpen, vbLf)
  If Left(fd(0), 1) = "-" Then
    Debug.Print "Canceled"
    Exit Sub
  End If

  slideWidth = ActivePresentation.PageSetup.SlideWidth
  slideHeight = ActivePresentation.PageSetup.SlideHeight

  count = 0
  For Each sld In ActivePresentation.Slides
    ' 跳过隐藏的 PPT 页
    If sld.SlideShowTransition.Hidden = msoFalse Then
      If count + LBound(fd) > UBound(fd) Then
        ' No picture to insert
        Exit For
      End If

      For i = 1 To numPicturePerSlide
        If count + LBound(fd) <= UBound(fd) Then
          Set shp = sld.Shapes.AddPicture( _
            FileName:=fd(count + LBound(fd)), _
            LinkToFile:=msoFalse, _
            SaveWithDocument:=msoTrue, _
            Left:=0, _
            Top:=0, _
            Width:=-1, _
            Height:=-1 _
          )
          With shp
            .LockAspectRatio = msoTrue  ' 锁定纵横比
            '.ScaleHeight 0.75, msoTrue
            .Left = slideWidth / numPicturePerSlide * i - .Width / 2
            .Top = (slideHeight - .Height) / 2
            '.ZOrder msoSendToBack   ' 将图片设置为最底层
          End With
          count = count + 1
        Else
          Exit For
        End If
      Next i
    End If
  Next sld

  'MsgBox "Processing finished. Inserted (" & count & ") pictures in total"
  MsgBox "插入图片完成,共插入 " & count & " 张图片"

End Sub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值