PowerPoint 2007 AutoSize property does not work

J

Jakob Lithner

I want to add a TextFrame to a PowerPoint slide and make sure there are no
text wraps. Instead the text size should decrease if necessary.

I tried the following code:
shape =
slide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 0,
0, 1280, 600);
shape.Name = "MyName1";
textFrame = shape.TextFrame;
textFrame.AutoSize = PpAutoSize.ppAutoSizeMixed;

The last line throws an ArgumentException:
"Input parameters are outside the interval." (My translation from swedish)

It works fine to set the other two enum values:
PpAutoSize.ppAutoSizeShapeToFitText
PpAutoSize.ppAutoSizeNone

I searched the internet and found out that many people have encountered the
same kind of problem, but just in PowerPoint 2007. Is there some kind of bug
here? Has the enum switched values that are no longer acceptable, or the
other way around?

Any workaround?
 
S

Steve Rindsberg

Jakob Lithner said:
I want to add a TextFrame to a PowerPoint slide and make sure there are no
text wraps. Instead the text size should decrease if necessary.

I tried the following code:
shape =
slide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 0,
0, 1280, 600);
shape.Name = "MyName1";
textFrame = shape.TextFrame;
textFrame.AutoSize = PpAutoSize.ppAutoSizeMixed;

The last line throws an ArgumentException:
"Input parameters are outside the interval." (My translation from swedish)

You can have the shape automatically resize to fit the text but the other way
around, shrinking the text to fit the text box, only works with body/title
placeholders, not with regular text boxes.

Something like this should work:

Dim oSh As Shape
Dim x As Double
Dim oSl As Slide
Set oSl = ActivePresentation.Slides(1)

Set oSh = oSl.Shapes.AddTextbox
(MsoTextOrientation.msoTextOrientationHorizontal, 0, 0, 720, 300)

With oSh
.Name = "MyName1"
.TextFrame.AutoSize = ppAutoSizeNone
With .TextFrame.TextRange
.Text = "Some really really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "terribly really really" _
& vbCrLf & "LONG text"
.Font.Size = 48
While .BoundHeight > oSh.Height
.Font.Size = .Font.Size - 1
Wend
End With
End With
 
J

Jakob Lithner

Thanks Steve.
I actually tried this as a workaround.
It works pretty well but when I do it live on a slide that is visible it
takes too long time. It gives a zooming (1-3 seconds) effect every time I
update the text content.

Either I have to rewrite the logic and create a shadow slide behind the
scene that is prepared before it is displayed, or just give up the whole
thing and decrease font size to be safe also for longer lines ....
 
T

Tim Li - MSFT

Hello Jakob,

Based on my experience PowerPoint doesn't not support this feature
natively, we have to find our own way to achieve it, when I saw Steve's
work around I think it is a very good one, even on my machine it performed
very well in performance. Would you please show us the code you have so
far, therefore, we could have a fully and clearly understand what is
happened related to the performance issue.

We are also finding another work around for you, but I think this may take
some time; I'll keep you updated if we have any new progress.

Best regards,
Tim Li
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).
 
J

Jakob Lithner

/// <summary>
/// Display text in prepared text slide.
/// </summary>
public void DisplayText(string lyrics)
{
SetActiveSlide(SlideType.Text);
var slide = presentation.Slides[SlideType.Text.ToString()];
SetText(slide, lyrics);
}



/// <summary>
/// Make sure relevant slide is displayed
/// </summary>
private void SetActiveSlide(SlideType slideType)
{
if (app != null)
{
if (app.SlideShowWindows.Count == 0)
throw new SongException("No active SlideShow");

SlideShowWindow slideShowWindow = app.SlideShowWindows[1];
SlideShowView view = slideShowWindow.View;
if (view.Slide.Name != slideType.ToString())
{
int slideIndex =
presentation.Slides[slideType.ToString()].SlideIndex;
view.GotoSlide(slideIndex, MsoTriState.msoTrue);
}
}
}


/// <summary>
/// Write texts into prepared sections of text slide.
/// </summary>
private void SetText(Slide slide, string lyrics)
{
// Set content of different text areas
slide.Shapes[1].TextFrame.TextRange.Text = lyrics;

// Reset the font size to the requested size so we don't get a small
size because of previous long text
slide.Shapes[1].TextFrame.TextRange.Font.Size = Config.MainTextSize;

// Make sure we have a font size that makes the text fit
AdjustTextSize(slide.Shapes[1]);
}


/// <summary>
/// Decrease font size until text frame fits into specified shape size.
/// </summary>
private static void AdjustTextSize(Shape shape)
{
var textRange = shape.TextFrame.TextRange;

while (textRange.BoundWidth > shape.Width || textRange.BoundHeight >
shape.Height)
{
textRange.Font.Size -= 1;
}
}
 
S

Steve Rindsberg

It doesn't look like your code is selecting the text, but have you manually
selected it before running the code? If the text is selected, PPT will try
to redraw it with every change to text size etc. Lots of screen activity.

There's a Win API that lets you lock screen updating; that's another
approach.
 
J

Jakob Lithner

Your reply gives me hope!

What do you mean by "selecting the text"?
In the SetText method I grab the shape/textframe/textrange and then change
the Text property. Then I run AdjustText changing the font size of the
textrange. Do you mean I should do it in another way that could avoid the
repeated updates?

What is the name of the WinAPI? Is it possible to decide what
screen/application/process to lock?
 
T

Tim Li - MSFT

Hello Jakob,

I've got the WinAPI, please refer to this link:
http://skp.mvps.org/ppt00033.htm
I've ran the code on my machine, and it works, hope this could help you to
deal with the problem.

Thanks.

Best regards,
Tim Li
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).
 
J

Jakob Lithner

The code suggested grabs the PowerPoint window which is not relevant.
We need to get hold of the slideshow window to get the desired effect.
Besides the app object is already known which means the FindWindow API is
not necessary.
I made these adjustments and finally got it to work :)

The code is still too slow but I got rid if the zooming.
On my DualCore 3 GHz, 8 Gb RAM, striped harddrives it takes 0.9 seconds
which is not very slow but still noticable. When changing the adjusting loop
to bigger steps I finally got it reasonable. Decreasing by 5% at the time got
me down to 0.2 seconds which is acceptable. I still need to check it on a
slower machine but this will probably do.

I enclose the reduced property in C# for reference.

// Use LockWindowUpdate to prevent/enable window refresh
[DllImport("user32", EntryPoint = "LockWindowUpdate", ExactSpelling = true,
CharSet = CharSet.Ansi, SetLastError = true)]
public static extern long LockWindowUpdate(long hwndLock);

// Use UpdateWindow to force a refresh of the PowerPoint window
[DllImport("user32", EntryPoint = "UpdateWindow", ExactSpelling = true,
CharSet = CharSet.Ansi, SetLastError = true)]
public static extern long UpdateWindow(long hwnd);

public bool ScreenUpdate
{
set
{
if (app.SlideShowWindows.Count == 0)
throw new SongException("No active PowerPoint SlideShow");

long appHandle = app.SlideShowWindows[1].HWND;

if (appHandle == 0)
throw new SongException("Unable to get the PowerPoint SlideShow
handle");

if (value == false)
{
// Lock the window
if (LockWindowUpdate(appHandle) == 0)
throw new SongException("Unable to set a PowerPoint
SlideShow window lock");
}
else
{
// Unlock the Window and refresh
LockWindowUpdate(0);
UpdateWindow(appHandle);
}
}
}
 
S

Steve Rindsberg

Your reply gives me hope!

What do you mean by "selecting the text"?

Let's consider that comment irrelevant ... you've since mentioned that you're
using Slide Show view; you *can't* select anything in that view, so we can
ignore that possibility.
In the SetText method I grab the shape/textframe/textrange and then change
the Text property. Then I run AdjustText changing the font size of the
textrange. Do you mean I should do it in another way that could avoid the
repeated updates?

What is the name of the WinAPI? Is it possible to decide what
screen/application/process to lock?

I see that Tim's supplied that answer; thanks Tim.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top