2015-09-19 18 views
6

Ich möchte eine Präsentation mit Daten aus einer Datenbank erstellen. Ich bekomme gültige Präsentationen, die in PowerPoint geöffnet werden (die Open XML Productivity Tool des SDK 2.5 ist eine große Hilfe dabei). Aber wie berechnet man die Größe der Textboxformen? Ich sehe, wo die Werte zu setzen sind, aber new Extents() Standardwerte auf Null Breite und Höhe. Wenn ich einige Werte einer Shape aus einer vorhandenen Präsentation nehme, kann ich die richtige Höhe bekommen (zumindest für Texte mit einer Zeile oder einer festen Anzahl von Zeilen), aber der Text wird nach rechts oder unten überlaufen (je nach Wortumbruch-Einstellung).Berechnen Sie die Größe (Extents) eines Textes (TextBody) in OpenXML (PresentationML) PowerPoint (PPTX)

Auch NormalAutoFit im BodyProperties des TextBody Einfügen nicht hilft - die erforderlichen Werte für FontScale und LineSpaceReduction werden nicht berechnet in OpenXML.

Also, was ist die beste Praxis für die Einstellung der Extents von Shape mit TextBody?

Gibt es einen eingebauten Weg, um die Extents einer gegebenen TextBody oder Shape zu berechnen? (Eine Faustregel mit eingebauten Methoden wäre besser als nichts)

Ich weiß, dass PowerPoint die Werte von NormalAutoFit nach jeder Änderung neu berechnet (zumindest für eine Reihe von Folien vor und nach dieser Änderung), Dies hilft jedoch nicht, wenn die Präsentation gestartet wird, bevor eine Änderung vorgenommen wurde (oder wenn sie mit dem PowerPoint-Viewer gestartet wurde).

+1

Ich habe das gleiche Problem und habe einige Fortschritte durch die Skalierung von den Ausmaßen zurück von TextRenderer.MeasureText() zum umgebenden Textfeld gemacht. Aber die Textgrößen sind nicht so eng um den Text wie die neu berechnete Skalierung von Powerpoint. Und ich bin ein bisschen weiter gekommen, indem ich die führende von der Höhe und die Zeichenbreite von der Breite abgezogen habe. Weitere Ideen sind willkommen. –

Antwort

3

Von Eric White's Forum

Dies ist eine nicht-triviale (aber machbar) Aufgabe.

Nach vielen Experimenten fand ich, dass die Textmetrikmethoden in System.Windows.Forms.TextRenderer mir die besten Ergebnisse gaben. Dies ist die Textmetrikfunktion, die WmlToHtmlConverter verwendet. Sie können den Code in WmlToHtmlConverter als ein Beispiel für die Verwendung von TextRenderer betrachten.

Hier ist der Code, den ich mit für meine Zwecke habe kommen basiert auf Eric White WmlToHtmlConverter, this post und this. Ich verwende dies, um die Abmessungen von TextBox für Textwasserzeichen und für Bildwasserzeichen für OpenXml für Word-Dokumente zu berechnen.

private static D.Size pixelsToEmus(int widthPx, int heightPx, double resDpiX, double resDpiY, int zoomX, int zoomY) 
    { 
     const int emusPerInch = 914400; 
     const int emusPerCm = 360000; 
     const decimal maxWidthCm = 16.51m; 
     var widthEmus = (int)(widthPx/resDpiX * emusPerInch) * zoomX/100; 
     var heightEmus = (int)(heightPx/resDpiY * emusPerInch) * zoomY/100; 
     var maxWidthEmus = (int)(maxWidthCm * emusPerCm); 
     if (widthEmus > maxWidthEmus) 
     { 
      var ratio = ((decimal)heightEmus/(decimal)widthEmus); 
      widthEmus = maxWidthEmus; 
      heightEmus = (int)(widthEmus * ratio); 
     } 
     return new D.Size(widthEmus, heightEmus); 
    } 

    public static D.Size GetTextSize(this CWatermarkItemBase watermark, string runText) 
    { 
     var fs = watermark.GetFontStyle(); 
     var sz = watermark.FontSize; 
     var proposedSize = new D.Size(int.MaxValue, int.MaxValue); 
     D.Size sf; 

     using (var ff = new D.FontFamily(watermark.FontFamily)) 
     { 
      try 
      { 
       using (var f = new D.Font(ff, (float)sz, fs)) 
       { 
        const TextFormatFlags tff = TextFormatFlags.NoPadding; 
        sf = TextRenderer.MeasureText(runText, f, proposedSize, tff); 
       } 
      } 
      catch (ArgumentException) 
      { 
       try 
       { 
        const D.FontStyle fs2 = D.FontStyle.Regular; 
        using (D.Font f = new D.Font(ff, (float)sz, fs2)) 
        { 
         const TextFormatFlags tff = TextFormatFlags.NoPadding; 
         sf = TextRenderer.MeasureText(runText, f, proposedSize, tff); 
        } 
       } 
       catch (ArgumentException) 
       { 
        const D.FontStyle fs2 = D.FontStyle.Bold; 
        try 
        { 
         using (var f = new D.Font(ff, (float)sz, fs2)) 
         { 
          const TextFormatFlags tff = TextFormatFlags.NoPadding; 
          sf = TextRenderer.MeasureText(runText, f, proposedSize, tff); 
         } 
        } 
        catch (ArgumentException) 
        { 
         // if both regular and bold fail, then get metrics for Times New Roman 
         // use the original FontStyle (in fs) 
         using (var ff2 = new D.FontFamily("Times New Roman")) 
         using (var f = new D.Font(ff2, (float)sz, fs)) 
         { 
          const TextFormatFlags tff = TextFormatFlags.NoPadding; 
          sf = TextRenderer.MeasureText(runText, f, proposedSize, tff); 
         } 
        } 
       } 
      } 
     } 
     D.Size s2 = pixelsToEmus(sf.Width, sf.Height, 96, 96, 100, 100); 
     return s2; 
    } 
    public static D.Size GetImageSize(this CWatermarkItemImage watermarkItem) 
    { 
     var img = new BitmapImage(new Uri(watermarkItem.FilePath, UriKind.RelativeOrAbsolute)); 
     return pixelsToEmus(img.PixelWidth, img.PixelHeight, img.DpiX, img.DpiY, watermarkItem.ZoomWidth, watermarkItem.ZoomHeight); 
    }