Showing posts with label csharp. Show all posts
Showing posts with label csharp. Show all posts

Thursday, June 13, 2013

Convert Word documents using Interop API

Have a requirement to convert millions of documents to html, preserving the formatting and style, so trying out Microsoft.Office.Interop.Word's SaveAs API.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Word = Microsoft.Office.Interop.Word;
using Microsoft.Office.Interop.Word;

public class WordTool: IDisposable
  {
    Word._Application oWord;
    object oMissing = System.Reflection.Missing.Value;
    object isVisible = true;
    object readOnly = true;
    object oSaveChanges = false;

    public WordTool()
    {
      // Create an instance of Word.exe
      oWord = new Word.Application();
      oWord.Visible = false;
      oWord.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
    }

    public void Convert(string input, string output)
    {
      WdSaveFormat format;
      switch (Path.GetExtension(output.ToLower()))
      {
        case ".doc":
          format = WdSaveFormat.wdFormatDocument;
          break;
        case ".docx":
          format = WdSaveFormat.wdFormatDocumentDefault;
          break;
        case ".htm":
          format = WdSaveFormat.wdFormatHTML;
          break;
        case ".html":
          format = WdSaveFormat.wdFormatFilteredHTML;
          break;
        case ".pdf":
          format = WdSaveFormat.wdFormatPDF;
          break;
        case ".rtf":
          format = WdSaveFormat.wdFormatRTF;
          break;
        case ".mht":
          format = WdSaveFormat.wdFormatWebArchive;
          break;
        case ".xps":
          format = WdSaveFormat.wdFormatXPS;
          break;
        case ".txt":
          format = WdSaveFormat.wdFormatTextLineBreaks;
          break;
        case ".xml":
          format = WdSaveFormat.wdFormatFlatXML;
          break;
        default:
          format = WdSaveFormat.wdFormatText;
          break;
      }

      object oFormat = format;
      object oInput = input;
      object oOutput = output;

      // Load a document into our instance of word.exe
      Word._Document oDoc = oWord.Documents.Open(ref oInput,
        ref oMissing, ref readOnly, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref isVisible, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing);

      // Make this document the active document.
      oDoc.Activate();

      // Save this document in Word 2003 format.
      oDoc.SaveAs(ref oOutput, ref oFormat,
        ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing);

      // found temp instance of doc if not closed
      oDoc.Close(ref oSaveChanges, ref oMissing, ref oMissing);
    }

    public void Dispose()
    {
      if (null != oWord)
        oWord.Quit(ref oSaveChanges, ref oMissing, ref oMissing);
    }
  }

This solution based on code originally found on Stack Overflow

Thursday, April 18, 2013

C# in memory XSLT processing

Needed to create an in memory (stream) based XSLT, was frustrated all the ready examples were file based, so documenting my solution for future reference and to share the love.

The convenience wrapper that references string names:


public static string DoXslTransform(string xslPath, string xmlBase, string relativeUri)
{

    XslCompiledTransform transform = 
      GetXslCompiledTransform(xslPath);

    Uri baseUri = new Uri(xmlBase);

    XmlReader xmlReader = GetXmlReader(baseUri, relativeUri);

    string data = GetXslToString(transform, xmlReader);

    xmlReader.Close();

    return data;
}

Method to create a stream based XmlReader:


public static XmlReader GetXmlReader(Uri baseUri, string relativeUri)
{
    XmlUrlResolver xmlUrlResolver = new XmlUrlResolver();

    xmlUrlResolver.Credentials = 
      System.Net.CredentialCache.DefaultCredentials;

    Uri fulluri = 
      xmlUrlResolver.ResolveUri(baseUri, relativeUri);

    Stream stream = (Stream)
      xmlUrlResolver.GetEntity(fulluri, null, typeof(Stream));
    return XmlReader.Create(stream);
}

Method to create a compiled transformer:


public static XslCompiledTransform GetXslCompiledTransform(string xslPath)
{
    XslCompiledTransform transform = new XslCompiledTransform();

    XmlReaderSettings xmlReaderSettings = 
      new XmlReaderSettings();
    xmlReaderSettings.DtdProcessing = DtdProcessing.Prohibit;
    xmlReaderSettings.CloseInput = true;

    XsltSettings xsltSettings = new XsltSettings(true, true);

    XmlResolver secureResolver = 
      new XmlSecureResolver(new XmlUrlResolver(), xslPath);

    transform.Load(XmlReader.Create(xslPath, xmlReaderSettings), 
      xsltSettings, secureResolver);

    return transform;
}

Method to do the transformation to string:


public static string GetXslToString(XslCompiledTransform transform, XmlReader xmlReader)
{
    MemoryStream memoryStream = 
      new MemoryStream();
    StreamWriter outStreamWriter = 
      new StreamWriter(memoryStream);

    transform.Transform(xmlReader, null, outStreamWriter);

    outStreamWriter.Flush();
    memoryStream.Position = 0;

    StreamReader reader = new StreamReader(memoryStream);
    
    return reader.ReadToEnd();
}


Friday, March 1, 2013

REST calls in CSharp

I needed to code set of REST calls in C# with a some specific requirements that prevented use of simpler WebClient API:


  • Setting the ContentType for "text/xml"
  • Support for GET, DELETE, and POST methods
  • The POST method had to submit data (an XML fragment) and also returned data (XML fragment)

Following is what I hacked out and documenting here so I don't have to look it up again.


XmlDocument RestGet(string uri)
{
    XmlDocument doc = new XmlDocument();

    HttpWebRequest request = 
     (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "GET";
    request.ContentType = "text/xml";

    HttpWebResponse response = 
     (HttpWebResponse)request.GetResponse();
    doc = new XmlDocument();
    doc.Load(response.GetResponseStream());
    response.Close();

    return doc;
}



static XmlDocument RestDelete(string uri)
{
    XmlDocument doc = new XmlDocument();

    HttpWebRequest request = 
     (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "DELETE";
    request.ContentType = "text/xml";

    HttpWebResponse response = 
     (HttpWebResponse)request.GetResponse();
    doc = new XmlDocument();
    doc.Load(response.GetResponseStream());
    response.Close();

    return doc;
}


static XmlDocument RestPost(string uri, string data)
{
    XmlDocument doc = new XmlDocument();

    HttpWebRequest request = 
     (HttpWebRequest)WebRequest.Create(uri);
    request.Method = "POST";
    request.ContentType = "text/xml";

    System.Text.UTF8Encoding encoding = 
     new System.Text.UTF8Encoding();
    byte[] byte1 = encoding.GetBytes(data);
    request.ContentLength = byte1.Length;

    Stream requestStream = request.GetRequestStream();
    requestStream.Write(byte1, 0, byte1.Length);
    requestStream.Close();

    HttpWebResponse response = 
     (HttpWebResponse)request.GetResponse();
    doc = new XmlDocument();
    doc.Load(response.GetResponseStream());
    response.Close();

    return doc;
}

Thursday, April 19, 2012

Reflection: Dynamically instantiating a class

The requirement was for a command line utility that accepted a "function" name and a list of parameters, where the parameters could be different for each function.

This is a fairly common requirement, which I don't want to have to look up again, so I thought I'd document my solution here.

My first thought was a switch on the function name, but that quickly became messy with the variable parameters. After consideration, it was simpler to implement each function as a class, then use reflection to instantiate the class and pass in command line parameters. To support dynamically creating the class, I used a common Interface with a Run method that accepted the command line parameters.

 namespace CodeExamples  
 {  
   interface IExample  
   {  
     void Run(string[] args);  
   }    
   class Program  
   {  
     static void Main(string[] args)  
     {  
       try  
       {  
         if (args.Length < 1)  
         {  
           Console.WriteLine("Syntax: CodeExample typeName [args]");  
         }  
         else  
         {  
           string assemblyName = "CodeExamples.";  
           string typeName = args[0];  
           Assembly = System.Reflection.Assembly.GetExecutingAssembly();  
           Type type = assembly.GetType(assemblyName + typeName);  
           IExample example = (IExample)Activator.CreateInstance(type);  
           example.Run(args);  
         }  
       }  
       catch (Exception e)  
       {  
         Console.WriteLine("\nEXCEPTION: {0}\n{1}", e.Message, e.StackTrace);  
       }  
     }  
   }  
 }  

Thursday, January 28, 2010

Simple way to output XML in ASP.NET MVC

Another post to document something that I really don't want to have to look up ever again. I simply wanted to output XML to the browser window using ASP.NET MVC. Sounds easy, simply use:
 
public ContentResult Index() 
{ 
StringWriter writer = new StringWriter();
myXmlDocument.Save(writer); 
return this.Content(writer.ToString(), @"text/xml", writer.Encoding);
} 


But no luck; IE7's CSS would not display the XML since IIS ASP.NET defaults to UTF-16 and the previous page was UTF-8? Yes, both pages were correctly tagged with there encoding and correctly identified by IE as UTF-8 or UTF-16. It just wouldn't process the later. Whats up with that; can't these MS kids get along. So did a search and found a soluiton posted by Robert McLaw using a modified StringWriter that accepted an encoding which would worked very nicely:
 

public class StringWriterWithEncoding : StringWriter 
{ 
Encoding encoding; 
public StringWriterWithEncoding(Encoding encoding)
{ 
 this.encoding = encoding; 
}
public override Encoding Encoding 
{
 get { return encoding; } 
} 
}

To implement, just use the new writer and set it's encoding as desired:
 
public ContentResult Index() 
{ 
StringWriterWithEncoding writer = new StringWriterWithEncoding(Encoding.UTF8); 
myXmlDocument.Save(writer); 
return this.Content(writer.ToString(), @"text/xml", writer.Encoding);
} 

The advantatage of using the StringWriterWithEncoding method over a custom view is that the code can be used in other, non HTML based applications for consistency.

Tuesday, January 5, 2010

Simple method to download Web resource

Had to look this up - again - so writing a quick note for future reference.

public static string Download(string url) 
{ 
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url); 
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); 
Stream stream = httpWebResponse.GetResponseStream(); 
StreamReader streamReader = new StreamReader(stream, Encoding.ASCII); 
return streamReader.ReadToEnd(); 
} 

Thursday, May 14, 2009

Register Application as a Url Protocol

There are times when it is appropriate for a desktop application to be called via a URL and be passed data, such as "myprotocol://open?id=100”. The following code shows how an application can self register itself to handle a URL protocol.

public void RegisterUrlProtocol(string myUrlProtocolName, bool force,) 
RegistryKey rKey = Registry.ClassesRoot.OpenSubKey(myUrlProtocolName, true); 
if (force || rKey == null) 
rKey = Registry.ClassesRoot.CreateSubKey(myUrlProtocolName); 
rKey.SetValue("", "URL:"+ myUrlProtocolName+" Protocol"); 
rKey.SetValue("URL Protocol", ""); 
rKey = rKey.CreateSubKey(@"shell\open\command"); 
rKey.SetValue("", "\"" + Application.ExecutablePath + "\" %1"); 
if (rKey != null) { rKey.Close(); 
} 

Tuesday, November 25, 2008

Setting the Style for div via C#.NET

Had to look this up again so documenting for quick reference. It's rather simple to set a div style using the following steps:

Step 1; The div must have a unique id and be configured with runat="server":
 <div id="myDivId" runat="server" class="head2"> 

Step 2; The code behind references the div as if it were any other Control on the page, using the Controls Style property to set a style attribute:
 myDivId.Style["background-color"] = "#ffdd77"; 

Tuesday, November 4, 2008

Setting the property for div in a ContentPlaceHolder

Following shows how to set the property for a div that is in a C#.NET ContentPlaceHolder found with Master Pages:

Step 1; in the aspx file, the div needs a unqiue id and set to runat="server":

 <asp:Content ID="conent1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server"> <div id="myDivId" runat="server" style="display: block;"> <p>foo bar</p> </div> </asp:Content> 

Step 2; In the aspx.cs file, the ContentPlaceHolderId is retrieved first using the Page.Master.FindControl and then used to reference the div:

 ContentPlaceHolder content = (ContentPlaceHolder)Page.Master.FindControl("ContentPlaceHolder1"); content.FindControl("myDivId").Visible = false;