I have some VBA code that automates a number of slide changes ready for me to PDF the sides. I'd like to add a line in to delete all comments from the sides.
Seems simple but have had no luck in finding this anywhere. Any help much appreciated
This will do the job for current versions of PPT. Versions prior to 2007 handled comments differently; I think this should still work with older presentations but you'd have to test for yourself if that's an issue. And MS is liable to make changes to the commenting mechanism at any time, so who knows what might or might not work in future. But for now:
Sub DeleteComments()
Dim oSl As Slide
Dim oCom As Comment
Dim x As Long
With ActivePresentation
For Each oSl In .Slides
For x = oSl.Comments.Count To 1 Step -1
oSl.Comments(x).Delete
Next
Next
End With
End Sub
Related
I'm wondering if Powerpoint has a feature where I can automatically add a formatted header to each slide that displays the section and/or chapter. I'm presenting my thesis, and it is divided into sections, like "method" or "evaluation", and I would love it if I could automatically display that in the header of each slide. Preferrably, this would be automatically fetched from my powerpoint sections.
I want this look, which I'm currently producing manually for each slide.
Here's a bit of starter code to get you the name of the section each slide belongs to.
Over to you to provide the code to add the text to each slide and position/format it.
Sub Test()
Dim oSl As Slide
' Make sure there ARE sections
If ActivePresentation.SectionProperties.Count > 0 Then
For Each oSl In ActivePresentation.Slides
Debug.Print GetSection(oSl)
Next
End If
End Sub
Function GetSection(oSl As Slide) As String
' Returns the name of the section that this slide belongs to.
With oSl
Debug.Print .sectionIndex
GetSection = ActivePresentation.SectionProperties.Name(.sectionIndex)
End With
PowerPoint has no function like this built-in.
However, like most Office products, PowerPoint does have a very powerful VBA macro engine, which would certainly be capable of doing this.
Your macro would have to capture the Section name based on whatever parameters you choose to use to mark that, and then it could place that information anywhere you please within subsequent slides.
Because slides are more about visual layout than programmatic auto-creation, this is something you'd have to build yourself.
I have recently been asked if I could make a macro in Excel VBA that will allow a user to type in two numbers and have it automatically drop to the next row. The purpose of this is so they can type in grades for a test two numbers at a time without pressing enter since they aren't great at typing.
When I first heard this he mentioned it was Visual Basic, so I figured I'd just use a TextChanging or TextChanged event in the cell range and have it work off that. However, I haven't been able to find any such event or anything resembling it in the documentation thus far. The first thing that I came across was Workbook_Change, but that only changes after you press enter which is useless to me. Someone else mentioned there is such an event, but couldn't name it directly and I haven't been able to find what they were talking about.
If anyone has any information on if such an event exists or is possible I'd love to know.
The Excel version is 2007 as far as I'm aware.
This, in my opinion, requires a non-programming solution. I absolutely sympathize - it is tough to watch people get old - but you have to draw the line somewhere - for their sake and yours. The enter key is the most basic part of a computer. You could probably write a macro that would automatically hit enter on every even(or odd depending) keystroke in excel - but you're going to run into other problems like not being able to use delete normally. And what if you do want to put a string of text in a cell(like the student's name)? Perhaps it is time to find a non-programming solution. By that I mean someone should have a candid conversation with him about how he wants to solve the problem. Personally, I would offer to type the numbers in for him, as I am accustomed to the number pad - but it is probably better to be more direct and start to discuss retirement.
See this discussion about the limitations of cell edit mode in excel:
http://www.mrexcel.com/forum/excel-questions/524860-call-macro-every-keystroke.html
If you're really heart-set on a programming solution, I would recommend some kind of keystroke logging add-in.
Good Luck.
You could use the Worksheet_SelectionChange event. It is triggered without enter, but it would be triggered a lot.
You could however also create a special user-form for typing in the data, but this might be more work than necessary.
The main problem with using my suggested event is, you will need it as trigger and trigger it yourself, when selecting the next row, so disable event handling before changing the selection.
Edit:
This is a quick solution (paste this into the vba-code of the desired worksheet):
Private Const clngColumnRightToLastGrade = 5
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Column = clngColumnRightToLastGrade Then
Application.EnableEvents = False
'offset selection, one row down, two cols to left
Target.Offset(1, -2).Select
Application.EnableEvents = True
End If
End Sub
This will set you one row down and to column C, everytime your selection changes to column E (=5).
You don't have to use a constant of course, you could specify the column to sense in the workbook, so your user might modify it easier by himself.
To make this as an optional feature, you could extend it to autogenerated code. What I have in mind is like a Ribbon-Button, which opens a setupForm to configure, and a Ribbon-Button to activate the configuration, which would place this code in the configured sheet. But this might be a bit over the top.
In Excel 2003, (may be different in Excel2007 ?!) the WorkSheet_Change event is triggered every time the value of a cell is changed wether it is by pressing enter, delete, selecting an other cell after modifying a cell or even when a vba script changes the value of a cell.
I would do something like that:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim RefRange As Range
Set RefRange = Intersect(ActiveSheet.Columns("??????????"), ActiveSheet.UsedRange)
If Not Intersect(Target, RefRange) Is Nothing Then
Target.Offset(0, 1).EntireColumn.Range("A1").Select
'Target.Offset(0, 1).EntireColumn.Range("A65536").End(xlUp).Offset(1,0).Select
End If
End Sub
(This seems mostly to be a PowerPoint 2007 specific problem, which I can't easily reproduce in PPT 2010)
Easy way to reproduce locally is to:
1) Insert a shape into blank slide
2) Run command: ActivePresentation.Slides(1).Shapes(1).Delete in immediate window in Visual Studio. (You can alternatively delete through C#)
3) Undo the deletion in the PowerPoint presentation (do this non-programatically)
For some reason, you cannot access the shape again using calls like:
ActivePresentation.Slides(1).Shapes(1) //Does not allow any methods/properties to work
The only thing I've remotely gotten is that through Selection.ShapeRange, you can kind of get a reference to the item, but most of the Properties/Methods throw ComExceptions when trying to using that object.
Does anyone know how I can re-get the shape or somehow refresh the presentation to get some clean Com Objects?
I can confirm in Ppt2007 SP3. Try as workaround .cut and .paste. Afterwards I was able to access the other methods/properties. - cheers, www.MSO-dlx.com
ActivePresentation.Slides(1).Shapes(1).Delete
Application.CommandBars.ExecuteMso "Undo" 'or manually Undo
ActiveWindow.Selection.SlideRange(1).Shapes(1).Cut
ActiveWindow.Selection.SlideRange(1).Shapes.Paste
ActiveWindow.Selection.SlideRange(1).Shapes(1).TextFrame.TextRange.Text = "ABC"
so, I can confirm that this is an issue; even in 2010 and found a "cheaper" alternative:
Public Sub arf()
Dim arf As Slide
Dim shape As shape
Dim shapes As shapes
Set shapes = ActivePresentation.Slides(1).shapes
Set shape = shapes(2)
shape.Select
shape.Delete
Application.CommandBars.ExecuteMso "Undo"
MsgBox ("shape: " & shape.Name & ",Type: " & shape.Type)
Set shapes = ActivePresentation.Slides(1).shapes
Set shape = Nothing
Set shape = shapes(2)
' Cut and paste makes this work, but not required...
'shape.Select
'shape.Cut
'shapes.Paste
'Set shape = Nothing
'Set shape = shapes(2)
Set arf = shape.Parent
MsgBox ("slide: " & arf.Name)
End Sub
Just now I have successfully solved the problem, share the web page which helped a lot : https://www.add-in-express.com/creating-addins-blog/2014/06/24/exception-hresult-0x800a01a8/
The critical point is releasing the object after deleting it,which is exactly as Skovly and sharkTwo did.However,I don't know how to do this using C#,and the link gave me the answer.
Marshal.ReleaseComObject(titleShape); titleShape = null;
Just like this.
was hoping their might be a way to visualize progress of the deletion of several files, I have an application that runs a cleanup when it's done, the directory it deletes is almost 3GB, so it would be nice to have a progress bar popup similar to the one that shows if you use the
Const FOF_CREATEPROGRESSDLG = &H0&
strTargetFolder = "C:\OfficeTemp"
Set oShell = CreateObject("Shell.Application")
Set objFolder = oShell.NameSpace(strTargetFolder)
objFolder.CopyHere "OfficeTemp\*.*", FOF_CREATEPROGRESSDLG
supposedly you can implement this with SHFileOperation, but I only see examples for using this in C++, anyone ever done this with VBScript?
C++ Win32 API Delete file with progress bar
My advise is don't do it if you want to keep yout script agile.
It's not the size in GB that takes long to delete, so for a couple of large files it's not suitable since before you get up your gui up and running and display some progress your filedelition allready could be done. You culd just show the filename as it is being deleted.
If it are many many small files that take longer the progress bar would be more suitable, only you need to do it in IE or another browser that you can script to and the result will never be very reliable nor beautifull. I've seen ActiveX objects that give such progress bar but even when you could use these you have problems. You need to know in advance how many files there are to be deleted and the divide the process in small steps and show the progress as a percentage of the total.
This alone could take as long as the deletion itself, vbscript is very slow in handling files.
Showing the files here would certainly slow down the process, you could show something like
1000 files deleted..
2000 files deleted..
so that the user knows there is something happening.
The fastest way do delete the map is by shelling out en let de OS take care of it, then wait for the process to end and resume the script from there.
For some of these aproaches i have samples, sorry that i can't give you and easy allproblemssolved answer.
For people on the look for a progressbar while copying, i found this in meanwhile, tested and working on Win7
Const FOF_CREATEPROGRESSDLG = &H0&
strTargetFolder = "D:\Scripts"
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(strTargetFolder)
objFolder.CopyHere "C:\Scripts\*.*", FOF_CREATEPROGRESSDLG
Using VBA inside Access2003/2007.
How to copy the contents of a string variable to the clipboard?
This site recommends a creating a zero length TextBox, copying the string to the TextBox, then running DoCmd.RunCommand acCmdCopy. Ugh. I mean, we may go down the route. But still. Ugh.
While the MS knowledgebase article shows us how to do it but it involves a number of Windows API calls. Yuk.
Are those the only two options?
VB 6 provides a Clipboard object that makes all of this extremely simple and convenient, but unfortunately that's not available from VBA.
If it were me, I'd go the API route. There's no reason to be scared of calling native APIs; the language provides you with the ability to do that for a reason.
However, a simpler alternative is to use the DataObject class, which is part of the Forms library. I would only recommend going this route if you are already using functionality from the Forms library in your app. Adding a reference to this library only to use the clipboard seems a bit silly.
For example, to place some text on the clipboard, you could use the following code:
Dim clipboard As MSForms.DataObject
Set clipboard = New MSForms.DataObject
clipboard.SetText "A string value"
clipboard.PutInClipboard
Or, to copy text from the clipboard into a string variable:
Dim clipboard As MSForms.DataObject
Dim strContents As String
Set clipboard = New MSForms.DataObject
clipboard.GetFromClipboard
strContents = clipboard.GetText
User Leigh Webber on the social.msdn.microsoft.com site posted VBA code implementing an easy-to-use clipboard interface that uses the Windows API:
http://social.msdn.microsoft.com/Forums/en/worddev/thread/ee9e0d28-0f1e-467f-8d1d-1a86b2db2878
You can get Leigh Webber's source code here
If this link doesn't go through, search for "A clipboard object for VBA" in the Office Dev Center > Microsoft Office for Developers Forums > Word for Developers section.
I created the two classes, ran his test cases, and it worked perfectly inside Outlook 2007 SP3 32-bit VBA under Windows 7 64-bit. It will most likely work for Access.
Tip: To rename classes, select the class in the VBA 'Project' window, then click 'View' on the menu bar and click 'Properties Window' (or just hit F4).
With his classes, this is what it takes to copy to/from the clipboard:
Dim myClipboard As New vbaClipboard ' Create clipboard
' Copy text to clipboard as ClipboardFormat TEXT (CF_TEXT)
myClipboard.SetClipboardText "Text to put in clipboard", "CF_TEXT"
' Retrieve clipboard text in CF_TEXT format (CF_TEXT = 1)
mytxt = myClipboard.GetClipboardText(1)
He also provides other functions for manipulating the clipboard.
It also overcomes 32KB MSForms_DataObject.SetText limitation - the main reason why SetText often fails. However, bear in mind that, unfortunatelly, I haven't found a reference on Microsoft recognizing this limitation.
-Jim
I couldn't figure out how to use the API using the first Google results. Fortunately a thread somewhere pointed me to this link:
http://access.mvps.org/access/api/api0049.htm
Which works nicely. :)
Easy TWO line code:
It's not so complicated, I don't understand why all solutions found in the net are so complicated.
Sub StoreData()
Set objCP = CreateObject("HtmlFile")
objCP.ParentWindow.ClipboardData.SetData "text", "Some text for clipboard"
End Sub
There are many examples listed here but none seem to cover the direct way of using the API that also works with Access and Excel 32 bit and 64 bit.
I don't want to steal anyone else's work so I'm pointing to an article that has a solution.
https://stackoverflow.com/a/35512118/1898524
Following up on David's idea, if you want to pass in an argument, it has to be double-quoted.
Public Sub SetClipboardText(ByVal Text As String)
Dim QuotedText As String
QuotedText = """" & Text & """"
Set HtmlFileObject = CreateObject("HtmlFile")
HtmlFileObject.ParentWindow.ClipboardData.SetData "text", Eval(QuotedText)
End Sub