Is it possible to get slide html of PPT in C#.
and also how can we crate new slide using html while creating presentation using interop?
You can read from PPT file and get the text out of each slide, see below for an example :
static void Main(string[] args)
{
Microsoft.Office.Interop.PowerPoint.Application PowerPoint_App = new Microsoft.Office.Interop.PowerPoint.Application();
Microsoft.Office.Interop.PowerPoint.Presentations multi_presentations = PowerPoint_App.Presentations;
Microsoft.Office.Interop.PowerPoint.Presentation presentation = multi_presentations.Open(#"C:\PPT\myPowerpoint.pptx");
string presentation_text = "";
for (int i = 0; i < presentation.Slides.Count; i++)
{
foreach (var item in presentation.Slides[i+1].Shapes)
{
var shape = (PowerPoint.Shape)item;
if (shape.HasTextFrame == MsoTriState.msoTrue)
{
if (shape.TextFrame.HasText == MsoTriState.msoTrue)
{
var textRange = shape.TextFrame.TextRange;
var text = textRange.Text;
presentation_text += text+" ";
}
}
}
}
PowerPoint_App.Quit();
Console.WriteLine(presentation_text);
}
Related
I am working on a WinForms application. I use the pdf file to reset the password and the values on pdf are stored as key-value pairs(email: xxxx#mail.com, pass: 11111).
What I want to do:
Read the PDF file line by line and fill the appropriate textboxes.
What I Have done:
public bool CreatePDF(string location, string email, string key)
{
if(location != "" && email != "" && key != "")
{
PdfWriter pdfwriter = new PdfWriter(location);
PdfDocument pdf = new PdfDocument(pdfwriter);
Document document = new Document(pdf);
Paragraph fields = new Paragraph("Email: "+email + "\n" + "Secret Key: "+key);
document.Add(fields);
document.Close();
return true;
}
else
{
return false;
}
}
public string ReadPDF(string location)
{
var pdfDocument = new PdfDocument(new PdfReader(location));
StringBuilder processed = new StringBuilder();
var strategy = new LocationTextExtractionStrategy();
string text = "";
for (int i = 1; i <= pdfDocument.GetNumberOfPages(); ++i)
{
var page = pdfDocument.GetPage(i);
text += PdfTextExtractor.GetTextFromPage(page, strategy);
processed.Append(text);
}
return text;
}
}
Thank you in advance Guys!. Any suggestions on CreatePDF are also welcome.
This is what I came up with,
var pdfDocument = new PdfDocument(new PdfReader("G:\\Encryption_File.pdf"));
StringBuilder processed = new StringBuilder();
var strategy = new LocationTextExtractionStrategy();
string text = "";
for (int i = 1; i <= pdfDocument.GetNumberOfPages(); ++i)
{
var page = pdfDocument.GetPage(i);
text += PdfTextExtractor.GetTextFromPage(page, strategy);
processed.Append(text);
}
text.Split('\n');
string line = "";
line = text + "&";
string[] newLines = line.Split('&');
textBox1.Text = newLines[0].Split(':')[1].ToString();
textBox2.Text = newLines[0].Split(':')[2].ToString();
I have an issue when I try to write multiple paragraphs in existing Shape. Only the first paragraph is written. I debug the code and I found that the Shape object as all the paragraphs I want. The problem is when I write to file I found only the first one. I share with you the project code.
class Program
{
public static void Run()
{
string dataDir = ConfigurationManager.AppSettings["directoryToSave"];
string srcDir = ConfigurationManager.AppSettings["Source"];
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string file = Path.Combine(appData, srcDir);
using (Presentation presentation = new Presentation(srcDir))
{
IMasterLayoutSlideCollection layoutSlides = presentation.Masters[0].LayoutSlides;
ILayoutSlide layoutSlide = null;
foreach (ILayoutSlide titleAndObjectLayoutSlide in layoutSlides)
{
if (titleAndObjectLayoutSlide.Name == "TITRE_CONTENU")
{
layoutSlide = titleAndObjectLayoutSlide;
break;
}
}
var contenu = File.ReadAllText(#"E:\DemosProject\PF_GEN\PF_GEN\Source\contenu.txt", Encoding.UTF8);
IAutoShape contenuShape = (IAutoShape)layoutSlide.Shapes.SingleOrDefault(r => r.Name.Equals("contenu"));
ITextFrame txt = ((IAutoShape)contenuShape).TextFrame;
txt.Paragraphs.Clear();
string[] lines = contenu.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Where(str => !String.IsNullOrEmpty(str)).ToArray();
for (int i = 0; i < lines.Length; i++)
{
var portion = new Portion();
portion.Text = lines[i];
var paragraphe = new Paragraph();
paragraphe.Portions.Add(portion);
txt.Paragraphs.Add(paragraphe);
}
presentation.Slides.InsertEmptySlide(0, layoutSlide);
presentation.Save(dataDir + "AddLayoutSlides_out.pptx", SaveFormat.Pptx);
}
}
static void Main(string[] args)
{
try
{
var path = ConfigurationManager.AppSettings["sourceAsposeLicensePath"];
License license = new License();
license.SetLicense(path);
Run();
}
catch (Exception ex)
{
Console.WriteLine("Error" + ex.Message);
}
finally
{
Console.WriteLine("Terminated");
Console.ReadKey();
}
}
}
You can find the ppt file (source file) in the attachement file. (https://gofile.io/?c=JpBDS8 1)
Is there any thing missing in my code?
Thanks
I have observed your requirements and suggest you to please try using following sample code on your end. In your sample code, you are adding different paragraphs to a shape inside LayoutSlide and then adding a slide using that LayoutSlide to contain the desired shape. This approach is not correct. You actually need to first add slide based on LayoutSlide and then add text to that shape as per your requirements. The following code will be helpful to you.
public static void RunParaText()
{
string path = #"C:\Aspose Data\";
string dataDir = path;
string srcDir = path + "Master.pptx";
//string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
//string file = Path.Combine(appData, srcDir);
using (Presentation presentation = new Presentation(srcDir))
{
IMasterLayoutSlideCollection layoutSlides = presentation.Masters[0].LayoutSlides;
ILayoutSlide layoutSlide = null;
foreach (ILayoutSlide titleAndObjectLayoutSlide in layoutSlides)
{
if (titleAndObjectLayoutSlide.Name == "TITRE_CONTENU")
{
layoutSlide = titleAndObjectLayoutSlide;
break;
}
}
var contenu = File.ReadAllText(dataDir+"contenu.txt", Encoding.UTF8);
var slide=presentation.Slides.InsertEmptySlide(0, layoutSlide);
IAutoShape contenuShape = (IAutoShape)slide.Shapes.SingleOrDefault(r => r.Name.Equals("contenu"));
//IAutoShape contenuShape = (IAutoShape)layoutSlide.Shapes.SingleOrDefault(r => r.Name.Equals("contenu"));
ITextFrame txt = ((IAutoShape)contenuShape).TextFrame;
txt.Paragraphs.Clear();
string[] lines = contenu.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Where(str => !String.IsNullOrEmpty(str)).ToArray();
for (int i = 0; i < lines.Length; i++)
{
var portion = new Portion();
portion.Text = lines[i];
var paragraphe = new Paragraph();
paragraphe.Portions.Add(portion);
txt.Paragraphs.Add(paragraphe);
}
//Change font size w.r.t shape size
contenuShape.TextFrame.TextFrameFormat.AutofitType = TextAutofitType.Normal;
presentation.Save(dataDir + "AddLayoutSlides_out.pptx", SaveFormat.Pptx);
}
}
I am working as Support developer/ Evangelist at Aspose.
When I try to save each page as GIF using ABCpdf, only the first page is saved.
For example: I have a PDF that has 3 pages. I use ABCpdf to render each page to a stream, which is saved to disk. When I open the files in my destination folder, all 3 files show the first page content.
Here's my code:
using (Doc theDoc = new Doc())
{
XReadOptions options = new XReadOptions { ReadModule = ReadModuleType.Pdf };
theDoc.Read(inputbytearray, options);
using (MemoryStream ms = new MemoryStream())
{
theDoc.Rendering.DotsPerInch = 150;
int n = theDoc.PageCount;
for (int i = 1; i <= n; i++)
{
Guid FileName = Guid.NewGuid();
theDoc.Rect.String = theDoc.CropBox.String;
theDoc.Rendering.SaveAppend = (i != 1);
theDoc.Rendering.SaveCompression = XRendering.Compression.G4;
theDoc.PageNumber = i;
theDoc.Rendering.Save(string.Format("{0}.gif", FileName), ms);
using (var streamupload = new MemoryStream(ms.GetBuffer(), writable: false))
{
_BlobStorageService.UploadfromStream(FileName.ToString(), streamupload, STR_Gif, STR_Imagegif);
}
}
// theDoc.Clear();
}
}
The Rendering.SaveAppend property is only applicable when saving TIFF images. For GIFs you would need to save a separate image for each PDF page.
private void button1_Click(object sender, System.EventArgs e)
{
string theDir = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName + #"\files\";
// Create test PDF
using (Doc doc = new Doc())
{
for (int i = 1; i <= 3; i++)
{
doc.Page = doc.AddPage();
doc.AddHtml("<font size=24>PAGE " + i.ToString());
}
doc.Save(Path.Combine(theDir, "test.pdf"));
}
// Save PDF pages to GIF streams
using (Doc doc = new Doc())
{
doc.Read(Path.Combine(theDir, "test.pdf"));
for (int i = 1; i <= doc.PageCount; i++)
{
doc.PageNumber = i;
doc.Rect.String = doc.CropBox.String;
using (MemoryStream ms = new MemoryStream())
{
doc.Rendering.Save("dummy.gif", ms);
using (FileStream fs = File.Create(Path.Combine(theDir, "p" + i.ToString() + ".gif")))
{
ms.Seek(0, SeekOrigin.Begin);
ms.CopyTo(fs);
}
}
}
}
}
I am creating a mail merge document using OpenXML dll. I have a requirement to add a dynamic table to the word document. Currently I have been able to add the table # the end of the document but I need to add it some where in the middle of the page.
I have 4 pages in the word document and this table has to be added to the start of the 3rd page. I have been able to get the table. The only issue that I have is to add the table here.
The following is the code:
void createTemplate(string newFileName,string folderName,ArrayList mailMergeList,DataTable observations)
{
FileInfo newFile = new FileInfo(newFileName);
if (!IsFileLocked(newFile))
{
//declare and open a Word document object
WordprocessingDocument objWordDocx = WordprocessingDocument.Open(newFileName, true);
//get the main document section of the document
OpenXmlElement objMainDoc = objWordDocx.MainDocumentPart.Document;
//var wordDoc = new Microsoft.Office.Interop.Word.Document();
//Loop through merge fields
string FieldDelimiter = " MERGEFIELD ";
foreach (FieldCode field in objWordDocx.MainDocumentPart.RootElement.Descendants<FieldCode>())
{
var fieldNameStart = field.Text.LastIndexOf(FieldDelimiter, System.StringComparison.Ordinal);
String fieldname = field.Text.Substring(fieldNameStart + FieldDelimiter.Length).Trim();
fieldname = fieldname.Substring(0, fieldname.IndexOf(' '));
// fieldname
var fieldValue = "";
fieldValue = GetMergeValue(fieldname, mailMergeList);
// Go through all of the Run elements and replace the Text Elements Text Property
foreach (Run run in objWordDocx.MainDocumentPart.Document.Descendants<Run>())
{
foreach (Text txtFromRun in run.Descendants<Text>().Where(a => a.Text == "«" + fieldname + "»"))
{
if (fieldname.Equals("ObservationsTable"))
{
//observations
if (observations.Rows.Count > 0) //only if there is data in the Resi Obs NOI sheet we need to create a table
{
txtFromRun.Text = CreateTable(objWordDocx, newFileName, observations).ToString();
}
}
else
{
txtFromRun.Text = GetMergeValue(fieldname, mailMergeList);
}
}
}
}
//save this part
objWordDocx.MainDocumentPart.Document.Save();
//save and close the document
objWordDocx.Close();
}
}
I have been given a solution below but it is not feasible for me as I am not using Word.Interop dll.
Please guide.
Here's an open xml example. I created a dummy table:
var tab = new Table();
for (var z = 0; z < 2; z++)
{
var tr = new TableRow();
for (var j = 0; j < 2; j++)
{
var tc = new TableCell();
tc.Append(new Paragraph(new Run(new Text("i: " + z + " j:" + j))));
tr.Append(tc);
}
tab.Append(tr);
}
In my word.docx I have:
Some text
«Table»
some other text
And to loop over the merge fields:
WordprocessingDocument objWordDocx = WordprocessingDocument.Open(newFileName, true);
OpenXmlElement objMainDoc = objWordDocx.MainDocumentPart.Document;
foreach (var field in objMainDoc.Descendants<SimpleField>())
{
if (field.Instruction.Value.Trim().EndsWith("Table"))
{
var tabRun = new Run(tab);
field.Parent.ReplaceChild<SimpleField>(tabRun, field);
}
}
objWordDocx.MainDocumentPart.Document.Save();
objWordDocx.Close();
EDIT:
Version with FieldCode:
foreach (var field in objMainDoc.Descendants<FieldCode>())
{
if (field.InnerText.Trim().EndsWith("Table"))
{
var tabRun = new Run(tab);
var anc = field.Ancestors<Paragraph>().FirstOrDefault();
anc.RemoveAllChildren();
anc.Append(tabRun);
}
}
Note: this works for me as the only thing in my paragrah is the field code. If you have stuff in your paragraph which shouldn't be removed, modify the code.
In your document (wordDoc below) add a mergefield, "CustomTable" for example.
Object oMissing = System.Reflection.Missing.Value;
Object oTemplatePath = templatePath; // Path
var wordApp = new Microsoft.Office.Interop.Word.Application();
var wordDoc = new Microsoft.Office.Interop.Word.Document();
wordDoc = wordApp.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
foreach (Field field in wordDoc.Fields)
{
var fieldText = field.Code.Text;
var fieldName = fieldText.Substring(11).Split(new string[] { "\\" }, StringSplitOptions.None)[0].Trim();
field.Select();
if (fieldText.StartsWith(" MERGEFIELD"))
{
if (fieldName == "CustomTable")
{
var tab = wordDoc.Tables.Add(wordApp.Selection.Range, noOfColumns, noOfRows);
tab.Cell(1, 1).Range.Text = "Some text";
// ETC
}
}
}
I am trying to save selected slide so it doesnt retain my source template. how do i retain the existing template while i save the slides
private void SaveSelectedSlide_Click(object sender, RibbonControlEventArgs e)
{
try
{
PowerPoint.Application ppApp = Globals.ThisAddIn.Application;
PowerPoint.SlideRange ppslr = ppApp.ActiveWindow.Selection.SlideRange;
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var temporaryPresentation = Globals.ThisAddIn.Application.Presentations.Add(Microsoft.Office.Core.MsoTriState.msoTrue);
Microsoft.Office.Interop.PowerPoint.CustomLayout customLayout = ppApp.ActivePresentation.SlideMaster.CustomLayouts[Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutText];
for (int i = 1; i <= ppslr.Count; i++)
{
var sourceSlide = ppslr[i];
sourceSlide.Copy();
var design = sourceSlide.Design;
temporaryPresentation.Slides.Paste();
}
temporaryPresentation.SaveAs("Temporary", Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType.ppSaveAsPresentation, Microsoft.Office.Core.MsoTriState.msoTrue);
temporaryPresentation.Close();
}
catch (COMException Ex)
{
Debug.WriteLine("Some problem" + Ex.Message + Ex.StackTrace);
MessageBox.Show("PLease enter text ");
}
}
I think I got what you want. When pasting the new slide, save the new SlideRange. Afterwards assign the design of the source slide.
PowerPoint.Application ppApp = Globals.ThisAddIn.Application;
PowerPoint.SlideRange ppslr = ppApp.ActiveWindow.Selection.SlideRange;
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var temporaryPresentation = Globals.ThisAddIn.Application.Presentations.Add(Microsoft.Office.Core.MsoTriState.msoTrue);
Microsoft.Office.Interop.PowerPoint.CustomLayout customLayout = ppApp.ActivePresentation.SlideMaster.CustomLayouts[Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutText];
for (int i = 1; i <= ppslr.Count; i++)
{
var sourceSlide = ppslr[i];
sourceSlide.Copy();
var design = sourceSlide.Design;
SlideRange sr = temporaryPresentation.Slides.Paste(); // get newly created slideRange
sr.Design = sourceSlide.Design; // manually set design
}
temporaryPresentation.SaveAs("Temporary", Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType.ppSaveAsPresentation, Microsoft.Office.Core.MsoTriState.msoTrue);
temporaryPresentation.Close();
It worked for me. Please let me know if this is the expected behaviour!