Joseph Michael Pesch
VP Programming

C# Draw Thermometer Goal

by 14. March 2012 07:59

This sample shows how to take a generic thermometer image (with transparent background and empty contents, i.e. outline only) and draw in the content using C#.  The base thermometer image is attached and full code sample below. 

Here are samples of the base image and a test output using the URL shown below:

DrawThermometer.aspx?colorString=%230A58BC&goalHeadText=Southwest Funding&goalBodyText=November Goal&goalAmt=75&actualAmt=55&amtSuffix=MM

Here is the sample code:

using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Drawing;

public partial class DrawThermometer : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    // Sample call:
    // DrawThermometer.aspx?colorString=%230A58BC&goalHeadText=Southwest Funding&goalBodyText=November Goal&goalAmt=75&actualAmt=55&amtSuffix=MM
    string colorString = Request.Params["colorString"];
    string goalHeadText = Request.Params["goalHeadText"];
    string goalBodyText = Request.Params["goalBodyText"];
    decimal goalAmt = Convert.ToDecimal(Request.Params["goalAmt"]);
    string amtSuffix = Request.Params["amtSuffix"];
    decimal actualAmt = 0;
    // ActualAmt is optional input parameter, when not provided we run a SQL query.
    if (Request.Params["actualAmt"] != null)
    {
      actualAmt = Convert.ToDecimal(Request.Params["actualAmt"]);
    }
    else
    {
      string sql = "select sum(SomeField) as actualAmt from SomeTable where Something = true";
      using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLCN"].ConnectionString))
      {
        using (SqlCommand cmd = new SqlCommand(sql, cn))
        {
          cn.Open();
          actualAmt = Convert.ToInt32(cmd.ExecuteScalar());
          actualAmt = Convert.ToDecimal(actualAmt * Convert.ToDecimal(.000001));
          cn.Close();
        }
      }
    }
    DrawImage(colorString, goalHeadText, goalBodyText, goalAmt, actualAmt, amtSuffix);
  }
  private void DrawImage(string colorString, string goalHeadText, string goalBodyText, decimal goalAmt, decimal actualAmt, string amtSuffix)
  {
    // Locals
    int width = 325;
    int height = 100;
    int barLeft = 83;
    int barTop = 44;
    int barWidth = 220;
    int barHeight = 29;
    int actualWidth = 0;
    int intervalWidth = 20;
    string val = string.Empty;
    ColorConverter converter = new ColorConverter();
    Color fillColor = (Color)converter.ConvertFromString(colorString);
    string imagePath = Server.MapPath("~/images/Thermometer.png");
    using (Image image = Image.FromFile(imagePath))
    {
      using (Graphics g = Graphics.FromImage(image))
      {
        Color color = fillColor;
        SolidBrush fillBrush = new SolidBrush(color);
        g.FillEllipse(fillBrush, new Rectangle(8, 23, 70, 70));
        g.FillRectangle(fillBrush, new Rectangle(barLeft - 10, barTop, 10, barHeight));
        actualWidth = Convert.ToInt32((Convert.ToDecimal(actualAmt) / Convert.ToDecimal(goalAmt)) * Convert.ToDecimal(barWidth));
        // Adjust for width of markers between bars...
        actualWidth = actualWidth - Convert.ToInt32((Convert.ToDecimal(actualAmt) / Convert.ToDecimal(goalAmt)) * 2);
        if (actualWidth > barWidth) actualWidth = barWidth;
        // TALL: Rectangle rect = new Rectangle(45, 135, 29, 145);
        // WIDE: Rectangle rect = new Rectangle(83, 44, 221, 29);
        Rectangle rect = new Rectangle(barLeft, barTop, actualWidth, barHeight);
        g.FillRectangle(fillBrush, rect);
        g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        g.DrawString(goalBodyText, new Font("Tahoma", 14, FontStyle.Bold), fillBrush, barLeft, barTop - 40); // use 28 when printing the goalHeadText...
        val = "$" + goalAmt.ToString() + amtSuffix;
        g.DrawString(val, new Font("Tahoma", 14, FontStyle.Bold), fillBrush, width - val.Length * 18, barTop - 40); // use 28 when printing the goalHeadText...
        // Draw the current actual number
        // TALL: g.DrawString("55.55", new Font("Tahoma", 10, FontStyle.Bold), Brushes.White, 40, 275);
        // WIDE: g.DrawString("55.55", new Font("Tahoma", 10, FontStyle.Bold), Brushes.White, 16, 39);
        val = "$" + actualAmt.ToString("#.00") + amtSuffix;
        g.DrawString(val, new Font("Tahoma", 12, FontStyle.Bold), Brushes.White
          , width - (barWidth - actualWidth) - 5 - (val.Length * 14), 47);
        // Draw the intervals
        bool target = false;
        for (int i = 1; i <= 10; i++)
        {
          Font font = new Font("Arial Narrow", 8, FontStyle.Bold);
          Brush brush = fillBrush;
          int interval = ((goalAmt > Convert.ToInt32(actualAmt)) ? Convert.ToInt32(goalAmt) : Convert.ToInt32(actualAmt)) / 10;
          int mark = i * interval;
          val = "" + mark.ToString();
          if (!target && (i.Equals(10) || ((mark >= goalAmt) || goalAmt - mark < interval / 2)))
          {
            target = true;
            font = new Font("Arial Narrow", 8, FontStyle.Bold);
            brush = Brushes.Red;
          }
          g.DrawRectangle(new Pen(Brushes.Black), barLeft - 2 + (intervalWidth * i), height - 60, 1, 8);
          g.DrawRectangle(new Pen(Brushes.Black), barLeft - 2 + (intervalWidth * i), height - 33, 1, 8);
          g.DrawString(val, font, brush, barLeft + (intervalWidth * i) - (val.Length * 4), height - 18);
        }
      }
      System.IO.MemoryStream stream = new System.IO.MemoryStream();
      image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
      Context.Response.BinaryWrite(stream.ToArray());
    }

  }

}

Thermometer.png (5.78 kb)

Tags:

C#

C# Upload Local Document to SharePoint Site

by 22. February 2012 10:17

Below is a sample windows service that will run daily.  This method is used to open a local Excel file, refresh it's data connection(s), save the updated file locally and finally, upload the local file to a SharePoint site.

Command prompts to Delete and Create the Windows Service:

sc delete ServiceNameHere
sc create ServiceNameHere binpath= "c:\pathtoexe\AutomationService.exe"

Sample App.Config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="FileDictionary" type="System.Configuration.DictionarySectionHandler" />
  </configSections>
  <FileDictionary>
    <add key="C:\Data\File1.xlsx" value="http://mysharepoint/sites/reports/File1.xlsx" />
    <add key="C:\Data\File2.xlsx" value="http://mysharepoint/sites/reports/File2.xlsx" />
  </FileDictionary>
</configuration>

Sample Code:

using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration;
using System.Net;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using Microsoft.Office.Interop.Excel;

namespace AutomationService
{
  public partial class AutomationServiceInstance : ServiceBase
  {

    string path = ConfigurationManager.AppSettings["FilePath"];
    // Go back one day so we run on start...
    DateTime lastRun = DateTime.Now.AddDays(-1);

    public AutomationServiceInstance()
    {
      InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
      System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
        , Char.ToString('\r') + Char.ToString('\n') 
        + "Starting service ... " + DateTime.Now.ToString());
      if(System.IO.File.Exists(path + @"\LastRun.txt"))
      {
        // If last run time file exists load the date/time from the file
        lastRun = Convert.ToDateTime(System.IO.File.ReadAllText(path + @"\LastRun.txt").Trim());
      }
      BackgroundWorker wkr = new BackgroundWorker();
      wkr.DoWork += TimeCycle;
      wkr.RunWorkerAsync();
    }

    protected override void OnStop()
    {
      System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
        , Char.ToString('\r') + Char.ToString('\n')
        + "Stopping service ... " + DateTime.Now.ToString());
    }


    protected void TimeCycle(object sender, DoWorkEventArgs e)
    {
      do
      {
        lastRun = Convert.ToDateTime(System.IO.File.ReadAllText(path + @"\LastRun.txt").Trim());
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n')
          + "Checking time ... " + DateTime.Now.ToString()
          + " lastRun: " + lastRun + "; curTime: " + DateTime.Now.ToString());
        if (!lastRun.DayOfYear.Equals(DateTime.Now.DayOfYear) 
          && DateTime.Now.TimeOfDay >= new TimeSpan(8,15,0)) ProcessIt();
        System.Threading.Thread.Sleep(60 * 1000);
      } while (true);
    }

    protected void ProcessIt()
    {
      // Key is the local source file, Value is the target web URL
      Hashtable tbl = (Hashtable)ConfigurationManager.GetSection("FileDictionary");
      foreach (DictionaryEntry de in tbl)
      {
        try
        {
          Application excel = new ApplicationClass();
          excel.DisplayAlerts = false;
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n')
            + "Begin processing ... " + DateTime.Now.ToString());
          string srcFile = de.Key.ToString();
          string outFile = de.Value.ToString();
          // Open the file 
          // Important, do not double up on objects in COM 
          // Notice the Workbooks variable used to open the workbook 
          // DO NOT DO THIS: Workbook wkb = excel.Workbooks.Open(srcFile, false, true); 
          Workbooks wkbs = excel.Workbooks;
          Workbook wkb = wkbs.Open(srcFile, false, true);
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n')
            + "     workbook open: " + DateTime.Now.ToString());
          wkb.EnableConnections();
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n')
            + "     connections enabled: " + DateTime.Now.ToString());
          wkb.RefreshAll();
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n')
            + "     workbook refreshed: " + DateTime.Now.ToString());
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n')
            + "Processing complete ... " + DateTime.Now.ToString());
          // Clean up to release resources 
          // IMPORTANT: This cleanup sequence was required when running 
          // this inside a service that remains open and recycles on a schedule 
          // otherwise multiple EXCEL processes would be running and resources 
          // left open causing file access problems and memory leaks. 
          GC.Collect();
          GC.WaitForPendingFinalizers();
          wkb.Close(false, Type.Missing, Type.Missing);
          Marshal.ReleaseComObject(wkb);
          Marshal.ReleaseComObject(wkbs);
          excel.Quit();
          Marshal.ReleaseComObject(excel);
          GC.Collect();
          GC.WaitForPendingFinalizers();
          if (WebClientUpload(srcFile, outFile, path))
          {
            lastRun = DateTime.Now;
            System.IO.File.WriteAllText(path + @"\LastRun.txt", lastRun.ToString());
          }
        }
        catch (Exception ex)
        {
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n')
            + "Exception occurred ... " + DateTime.Now.ToString());
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n') + ex.Message);
          System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
            , Char.ToString('\r') + Char.ToString('\n') + ex.StackTrace);
        }
      }
    }
    static bool WebClientUpload(string SourcePath, string TargetPath, string LogPath)
    {
      WebClient wc = new WebClient();
      wc.UseDefaultCredentials = true;
      try
      {
        byte[] response = wc.UploadFile(TargetPath, "PUT", SourcePath);
      }
      catch (WebException ex)
      {
        System.IO.File.AppendAllText(LogPath + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n')
          + "Exception occurred ... " + DateTime.Now.ToString());
        System.IO.File.AppendAllText(LogPath + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') + ex.Message);
        System.IO.File.AppendAllText(LogPath + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') + ex.StackTrace);
        return false;
      }
      return true;
    }
  }
}

Tags:

C# | Excel | Sharepoint

Excel to PDF Conversion Using Office Automation

by 31. January 2012 08:17

I wrote a simple C# method to open and Excel file and save it as PDF using basic Microsoft Office automation via the Excel COM.  In my case this method was inside a Windows Service that was scheduled to refresh the external data links (to datawarehouse and SSAS cube).  The initial code was problematic in that after the initial execution the output PDF file would often be locked causing the subsequent executions to fail.  Restarting the service would release the file, so it was apparent that the method was not cleanly releasing it's resources at end of execution. After some research and testing I now have a cleanup sequence that seems to reliably releasing all the resources so the service can now run indefinitely without conflict.  Below is a subset of the C# Excel COM code that illustrates the basic steps.

As a side note, while researching this issue I found an interesting article on using OpenOffice to perform a similar operation.  In my case I'm not sure it would work (at least not without further research and extending the method), as I need to refresh external data connections (which was not a feature covered in the sample I found).  However, it did sound like an interesting option as it only requires a few DLL's and not the full application install that the Office COM automation seems to require.  I included a simple version of the OpenOffice code (along with a reference link to the original article I read) below as well.  I will try to research this option later and update my post with the findings. 

Important side note:  Running this code on a Windows 2008 Server will fail with generic file access error if you don't have the folders shown below (i.e. create empty folder to resolve the issue):

  • Windows 2008 Server x64: C:\Windows\SysWOW64\config\systemprofile\Desktop
  • Windows 2008 Server x86: C:\Windows\System32\config\systemprofile\Desktop

 

Microsoft Excel Sample Code:

// Start application
Application excel = new ApplicationClass();
// Turn off message boxes
excel.DisplayAlerts = false;

string sourceFilePath = @"C:\SourceFile.xls"; 
string targetFilePath = @"C:\TargetFile.pdf";  

// Open the file
// Important, do not double up on objects in COM
// Notice the Workbooks variable used to open the workbook
// DO NOT DO THIS: Workbook wkb = excel.Workbooks.Open(sourceFilePath, false, true);
Workbooks wkbs = excel.Workbooks;
Workbook wkb = wkbs.Open(sourceFilePath, false, true);

// Refresh data connections and do some formatting
wkb.EnableConnections();
wkb.RefreshAll();
Worksheet sht = wkb.Worksheets["Summary"] as Worksheet;
sht.get_Range("A1").EntireColumn.ColumnWidth = 21;
sht.get_Range("B1", "E1").EntireColumn.AutoFit();
sht.get_Range("A1").Select();

// Delete target file
File.Delete(targetFilePath);

// Export to PDF
sht.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF
, targetFilePath, Microsoft.Office.Interop.Excel.XlFixedFormatQuality.xlQualityStandard
, true, false, Type.Missing, Type.Missing, false, Type.Missing);

// Clean up to release resources
// IMPORTANT: This cleanup sequence was required when running
// this inside a service that remains open and recycles on a schedule
// otherwise multiple EXCEL processes would be running and resources
// left open causing file access problems and memory leaks.
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(sht);
wkb.Close(false, Type.Missing, Type.Missing);
Marshal.ReleaseComObject(wkb);
Marshal.ReleaseComObject(wkbs);
excel.Quit();
Marshal.ReleaseComObject(excel);
GC.Collect();
GC.WaitForPendingFinalizers();

Here is a good article on cleaning up Excel COM objects: http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c-sharp.

OpenOffice Sample Code:

/*
You need the following DLL's from OpenOffice and reference them in your project:

cli_basetypes.dll 
cli_cppuhelper.dll 
cli_oootypes.dll 
cli_uno.dll 
cli_ure.dll 
cli_uretypes.dll 
*/

//...
using System;
using uno.util; 
using unoidl.com.sun.star.lang; 
using unoidl.com.sun.star.uno; 
using unoidl.com.sun.star.bridge; 
using unoidl.com.sun.star.frame; 
using unoidl.com.sun.star.text; 
using unoidl.com.sun.star.beans; 
using unoidl.com.sun.star.util;  
//...
  
string sourceFilePath = "file:///C:/SourceFile.xls"; 
string targetFilePath = "file:///C:/TargetFile.pdf";  

// Start OpenOffce or get a reference to an existing session 
XComponentContext localContext = Bootstrap.bootstrap(); 
XMultiServiceFactory multiServiceFactory = (XMultiServiceFactory)localContext.getServiceManager(); 
XComponentLoader componentLoader = (XComponentLoader)multiServiceFactory.createInstance("com.sun.star.frame.Desktop");  

// Set the file open properties
PropertyValue[] openProperties = new PropertyValue[2]; 
// Hidden...
openProperties[1] = new PropertyValue(); 
openProperties[1].Name = "Hidden"; 
openProperties[1].Value = new uno.Any(true);  
// Read only...
openProperties[0] = new PropertyValue(); 
openProperties[0].Name = "ReadOnly"; 
openProperties[0].Value = new uno.Any(true); 
// Open the file 
XComponent sourceDocument = componentLoader.loadComponentFromURL(sourceFilePath, "_blank", 0, openProperties);  

// Conversion parameters - overwrite existing file, use PDF exporter 
PropertyValue[] conversionProperties = new PropertyValue[3]; 
conversionProperties[0] = new PropertyValue(); 
conversionProperties[0].Name = "Overwrite"; 
conversionProperties[0].Value = new uno.Any(true); 
conversionProperties[1] = new PropertyValue(); 
conversionProperties[1].Name = "FilterName"; 
conversionProperties[1].Value = new uno.Any("calc_pdf_Export");  

// Set PDF export parameters 
PropertyValue[] filterData = new PropertyValue[3];  
// JPEG compression quality 70 
filterData[0] = new PropertyValue(); 
filterData[0].Name = "Quality"; 
filterData[0].Value = new uno.Any(70); 
filterData[0].State = PropertyState.DIRECT_VALUE;  
// Max image resolution 300dpi 
filterData[1] = new PropertyValue(); 
filterData[1].Name = "ReduceImageResolution"; 
filterData[1].Value = new uno.Any(true); 
filterData[1].State = PropertyState.DIRECT_VALUE; 
filterData[2] = new PropertyValue(); 
filterData[2].Name = "MaxImageResolution"; 
filterData[2].Value = new uno.Any(300); 
filterData[2].State = PropertyState.DIRECT_VALUE;  
conversionProperties[2] = new PropertyValue(); 
conversionProperties[2].Name = "FilterData"; 
conversionProperties[2].Value = new uno.Any(filterData.GetType(), filterData);  
// Export the PDF 
XStorable xstorable = (XStorable)sourceDoc; 
xstorable.storeToURL(pdfFile, conversionProperties);  

// Close document 
((XCloseable)sourceDoc).close(false); 
((XCloseable)xstorable).close(false);

OpenOffice API documentation can be found here: http://www.openoffice.org/api/.  Here is a link to the artical I used for basis of OpenOffice version of code: http://stackoverflow.com/questions/769246/xls-to-pdf-conversion-inside-net).

Tags:

C# | Excel

Excel to PDF Conversion Using Office Automation and/or Open Office

by 30. January 2012 10:23

One option to converting Excel documents to PDF is using Microsoft Office automation.  However, this requires installing the full application on the server that will be performing the automation (see this link for more details on that: ).  Another alternate solution is to switch to OpenOffice which only requires installing a few DLL's on the automation server.  Another option that I will review in the future is using the "ExcelLibrary" http://code.google.com/p/excellibrary/downloads/list

Microsoft Excel Sample Code:

// Start application
Application excel = new ApplicationClass();
// Turn off message boxes
excel.DisplayAlerts = false;

string sourceFilePath = @"C:\SourceFile.xls"; 
string targetFilePath = @"C:\TargetFile.pdf";  

// Open the file
// Important, do not double up on objects in COM
// Notice the Workbooks variable used to open the workbook
// DO NOT DO THIS: Workbook wkb = excel.Workbooks.Open(sourceFilePath, false, true);
Workbooks wkbs = excel.Workbooks;
Workbook wkb = wkbs.Open(sourceFilePath, false, true);

// Refresh data connections and do some formatting
wkb.EnableConnections();
wkb.RefreshAll();
Worksheet sht = wkb.Worksheets["Summary"] as Worksheet;
sht.get_Range("A1").EntireColumn.ColumnWidth = 21;
sht.get_Range("B1", "E1").EntireColumn.AutoFit();
sht.get_Range("A1").Select();

// Delete target file
File.Delete(targetFilePath);

// Export to PDF
sht.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF
, targetFilePath, Microsoft.Office.Interop.Excel.XlFixedFormatQuality.xlQualityStandard
, true, false, Type.Missing, Type.Missing, false, Type.Missing);

// Clean up to release resources
// IMPORTANT: This cleanup sequence was required when running
// this inside a service that remains open and recycles on a schedule
// otherwise multiple EXCEL processes would be running and resources
// left open causing file access problems and memory leaks.
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(sht);
wkb.Close(false, Type.Missing, Type.Missing);
Marshal.ReleaseComObject(wkb);
Marshal.ReleaseComObject(wkbs);
excel.Quit();
Marshal.ReleaseComObject(excel);
GC.Collect();
GC.WaitForPendingFinalizers();

Here is a good article on cleaning up Excel COM objects: http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c-sharp.

OpenOffice Sample Code:

/*
You need the following DLL's from OpenOffice and reference them in your project:

cli_basetypes.dll 
cli_cppuhelper.dll 
cli_oootypes.dll 
cli_uno.dll 
cli_ure.dll 
cli_uretypes.dll 
*/

//...
using System;
using uno.util; 
using unoidl.com.sun.star.lang; 
using unoidl.com.sun.star.uno; 
using unoidl.com.sun.star.bridge; 
using unoidl.com.sun.star.frame; 
using unoidl.com.sun.star.text; 
using unoidl.com.sun.star.beans; 
using unoidl.com.sun.star.util;  
//...
  
string sourceFilePath = "file:///C:/SourceFile.xls"; 
string targetFilePath = "file:///C:/TargetFile.pdf";  

// Start OpenOffce or get a reference to an existing session 
XComponentContext localContext = Bootstrap.bootstrap(); 
XMultiServiceFactory multiServiceFactory = (XMultiServiceFactory)localContext.getServiceManager(); 
XComponentLoader componentLoader = (XComponentLoader)multiServiceFactory.createInstance("com.sun.star.frame.Desktop");  

// Set the file open properties
PropertyValue[] openProperties = new PropertyValue[2]; 
// Hidden...
openProperties[1] = new PropertyValue(); 
openProperties[1].Name = "Hidden"; 
openProperties[1].Value = new uno.Any(true);  
// Read only...
openProperties[0] = new PropertyValue(); 
openProperties[0].Name = "ReadOnly"; 
openProperties[0].Value = new uno.Any(true); 
// Open the file 
XComponent sourceDocument = componentLoader.loadComponentFromURL(sourceFilePath, "_blank", 0, openProperties);  

// Conversion parameters - overwrite existing file, use PDF exporter 
PropertyValue[] conversionProperties = new PropertyValue[3]; 
conversionProperties[0] = new PropertyValue(); 
conversionProperties[0].Name = "Overwrite"; 
conversionProperties[0].Value = new uno.Any(true); 
conversionProperties[1] = new PropertyValue(); 
conversionProperties[1].Name = "FilterName"; 
conversionProperties[1].Value = new uno.Any("calc_pdf_Export");  

// Set PDF export parameters 
PropertyValue[] filterData = new PropertyValue[3];  
// JPEG compression quality 70 
filterData[0] = new PropertyValue(); 
filterData[0].Name = "Quality"; 
filterData[0].Value = new uno.Any(70); 
filterData[0].State = PropertyState.DIRECT_VALUE;  
// Max image resolution 300dpi 
filterData[1] = new PropertyValue(); 
filterData[1].Name = "ReduceImageResolution"; 
filterData[1].Value = new uno.Any(true); 
filterData[1].State = PropertyState.DIRECT_VALUE; 
filterData[2] = new PropertyValue(); 
filterData[2].Name = "MaxImageResolution"; 
filterData[2].Value = new uno.Any(300); 
filterData[2].State = PropertyState.DIRECT_VALUE;  
conversionProperties[2] = new PropertyValue(); 
conversionProperties[2].Name = "FilterData"; 
conversionProperties[2].Value = new uno.Any(filterData.GetType(), filterData);  
// Export the PDF 
XStorable xstorable = (XStorable)sourceDoc; 
xstorable.storeToURL(pdfFile, conversionProperties);  

// Close document 
((XCloseable)sourceDoc).close(false); 
((XCloseable)xstorable).close(false);

OpenOffice API documentation can be found here: http://www.openoffice.org/api/.  Here is a link to the artical I used for basis of OpenOffice version of code: http://stackoverflow.com/questions/769246/xls-to-pdf-conversion-inside-net).

Tags:

C# | Excel

C# Determine if Folder is Empty

by 28. January 2012 21:25
if (!Directory.EnumerateFileSystemEntries(FolderPath).Any())
{ 
  System.Diagnostics.Debug.WriteLine("Folder is empty");
}

Tags:

C#

Transform URL List into HTML Unordered List

by 23. January 2012 16:16
This method will take a flat list of fully qualified URL's and transform them into nested bullets (i.e. HTML unordered lists).  It is a simple method to convert the flat list of URL's into a psuedo tree view.  Here is the C# code to transform the list.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Xsl;

namespace UrlListToSiteMap
{
  public class Program
  {
    public static void Main(string[] args)
    {
      /*
         This method accepts a text file of fully qualified URLs 
         and will convert into HTML unordered list. 
      */
      string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
      List urlRecords = File.ReadAllLines(path + @"\UrlList.txt").ToList();
      urlRecords.Sort();
      XmlDocument doc = new XmlDocument();
      doc.AppendChild(doc.CreateNode(XmlNodeType.Element, "SiteMap", ""));
      XmlNode rootNod = doc.ChildNodes[0];
      foreach (string url in urlRecords)
      {
        XmlNode pathNod = rootNod;
        int iNod = 0;
        int iNods = url.ToLower()
          .Replace(@"http://", "").Replace("'", "").Split('/').Count();
        foreach (string nod in url.ToLower()
          .Replace(@"http://", "").Replace("'", "").Split('/'))
        {
          iNod++;
          System.Diagnostics.Debug.WriteLine(nod);
          XmlNode subNod = pathNod.SelectSingleNode("Node[@URL='" + nod + "']");
          if (subNod == null)
          {
            System.Diagnostics.Debug.WriteLine(pathNod.Name);
            string nodType = iNod.Equals(iNods) ? "Leaf" : "Node";
            subNod = doc.CreateNode(XmlNodeType.Element, nodType, "");
            XmlAttribute atr = doc.CreateAttribute("URL");
            atr.Value = nod;
            subNod.Attributes.Append(atr);
            pathNod.AppendChild(subNod);
          }
          pathNod = subNod;
        }
      }
      doc.Save(path + @"\SiteMap.xml");
      XslTransform xslt;
      xslt = new XslTransform();
      xslt.Load(path + "SiteMap.xslt");
      xslt.Transform(path + "SiteMapNew.xml", path + "SiteMap.html");
    }
  }
}

Attached is the XSLT file for the transformation. NOTE: If you only want the folders and not the actual documents, remove the "Leaf" section from the XSLT.

SiteMap.xslt (583.00 bytes)

Tags:

C# | HTML

CheckSum Utility

by 2. January 2012 16:32

Below is a C# implementation of two CheckSum utilities, the SHA256Managed uses the native .Net Security.Cryptography; while the Md5SumByProcess uses a windows implementation of Unix MD5Sum.exe (zip file attached to this blog can be downloaded from SourceForge at: http://sourceforge.net/projects/unxutils/files/unxutils/current/UnxUtils.zip/download). 

using System;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;

  class CheckSumUtil
  {
    public static string Md5SumByProcess(string file)
    {
      var p = new Process();
      p.StartInfo.FileName = "md5sum.exe";
      p.StartInfo.Arguments = file;
      p.StartInfo.UseShellExecute = false;
      p.StartInfo.RedirectStandardOutput = true;
      p.Start();
      p.WaitForExit();
      string output = p.StandardOutput.ReadToEnd();
      return output.Split(' ')[0].Substring(1).ToUpper();
    }

    public static string SHA256Managed(string file)
    {
      using(var stream = new BufferedStream(File.OpenRead(file), 1200000))
      {     
        SHA256Managed sha = new SHA256Managed();
        byte[] checksum = sha.ComputeHash(stream);
        return BitConverter.ToString(checksum).Replace("-", String.Empty);
      }
    }

  }
}

UnxUtils.zip (3.21 mb)

Tags:

C#

Windows Automation Service to Refresh Excel Workbook Data and Email PDF Export

by 12. December 2011 08:33

This was built to refresh an Excel file that has pivot tables built agains SSAS cube, format the spreadsheet, export it to PDF and email the PDF file. 

IMPORTANT NOTE: See this blog entry for potential issue when running Excel Automation code inside of a Windows Service: http://blog.tutorem.com/post/2011/12/12/Excel-Automation-Issue-Access-File-When-Running-as-a-Windows-Service.aspx

using System;
using System.ComponentModel;
using System.Configuration;
using System.ServiceProcess;
using Microsoft.Office.Interop.Excel;

namespace AutomationService
{
  public partial class AutomationServiceInstance : ServiceBase
  {

    string path = @"C:\ExcelAutomation";
    // Go back one day so we run on start...
    DateTime lastRun = DateTime.Now.AddDays(-1);
    Application excel = new ApplicationClass();

    public AutomationServiceInstance()
    {
      InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
      System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
        , Char.ToString('\r') + Char.ToString('\n') 
        + "Starting service ... " + DateTime.Now.ToString());
      if(System.IO.File.Exists(path + @"\LastRun.txt"))
      {
        // If last run time file exists load the date/time
        lastRun = Convert.ToDateTime(
          System.IO.File.ReadAllText(path + @"\LastRun.txt").Trim());
      }
      BackgroundWorker wkr = new BackgroundWorker();
      wkr.DoWork += TimeCycle;
      wkr.RunWorkerAsync();
    }

    protected override void OnStop()
    {
      System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
        , Char.ToString('\r') + Char.ToString('\n')
        + "Stopping service ... " + DateTime.Now.ToString());
    }


    protected void TimeCycle(object sender, DoWorkEventArgs e)
    {
      excel.DisplayAlerts = false;
      do
      {
        if (!lastRun.DayOfYear.Equals(DateTime.Now.DayOfYear) 
          && DateTime.Now.TimeOfDay >= new TimeSpan(8,15,0)) ProcessIt();
        System.Threading.Thread.Sleep(60 * 1000);
      } while (true);
    }

    protected void ProcessIt()
    {
      try
      {
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "Begin processing ... " + DateTime.Now.ToString());
        string srcFile = path + @"\SourceFile.xlsx";
        string outFile = path + @"\OutputFile.pdf";
        Workbook wkb = excel.Workbooks.Open(srcFile, false, true);
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "     workbook open: " + DateTime.Now.ToString());
        wkb.EnableConnections();
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "     connections enabled: " + DateTime.Now.ToString());
        wkb.RefreshAll();
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "     workbook refreshed: " + DateTime.Now.ToString());
        Worksheet sht = wkb.Worksheets["Pipeline Totals"] as Worksheet;
        // Format column A to a fixed width
        sht.get_Range("A1").EntireColumn.ColumnWidth = 20;
        // Format columns B through Z to auto fit width
        sht.get_Range("B1", "Z1").EntireColumn.AutoFit();
        // Navigate to first cell
        sht.get_Range("A1").Select();
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "     formatting complete: " + DateTime.Now.ToString());
        sht.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF
          , outFile, Microsoft.Office.Interop.Excel.XlFixedFormatQuality.xlQualityStandard
          , true, false, Type.Missing, Type.Missing, false, Type.Missing);
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "     export complete: " + DateTime.Now.ToString());
        wkb.Close(false, Type.Missing, Type.Missing);
        excel.Quit();
        MailUtil.SendMail("sender@domain.com", "Sender Name"
          , ConfigurationManager.AppSettings["EmailDistributionListTo"]
          , ConfigurationManager.AppSettings["EmailDistributionListCC"]
          , ConfigurationManager.AppSettings["EmailDistributionListBCC"]
          , "Excel Automation Report", false, "", outFile);
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "     mail sent: " + DateTime.Now.ToString());
        sht = null;
        wkb = null;
        lastRun = DateTime.Now;
        System.IO.File.WriteAllText(path + @"\LastRun.txt", lastRun.ToString());
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "Processing complete ... " + DateTime.Now.ToString());
      }
      catch (Exception ex)
      {
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') 
          + "Exception occurred ... " + DateTime.Now.ToString());
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') + ex.Message);
        System.IO.File.AppendAllText(path + @"\AutomationServiceLog.txt"
          , Char.ToString('\r') + Char.ToString('\n') + ex.StackTrace);
      }
    }

  }
}

Tags:

C# | Excel

Excel Automation Issue Access File When Running as a Windows Service

by 12. December 2011 07:30

I wrote an Excel automation process that worked fine as a Console Application, then I converted it to a Windows Service and it would error out at the point of trying to open the file with the following file access error shown below. 

To see a copy of the complete Windows Service code view this blog entry: http://blog.tutorem.com/post/2011/12/12/Windows-Automation-Service-to-Refresh-Excel-Workbook-Data-and-Email-PDF-Export.aspx

--------------------------------------------------------------------------------------------------
SOURCE: Microsoft Office Excel
MESSAGE: Microsoft Office Excel cannot access the file 'C:\PathToFile\File.xlsx'.

There are several possible reasons:

• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.
--------------------------------------------------------------------------------------------------

This did not make sense as nothing changed between the Console Application code and the Windows Service code.  So, I assumed it was a permission issue.  Tried all sorts of permissions tests with folders/file, as well as the windows service login account, etc.  Still no luck.  Then found a post with a simple solution shown below:

http://social.msdn.microsoft.com/For...?prof=required

For 64-bit (x64), create this folder:
C:\Windows\SysWOW64\config\systemprofile\Desktop

For 32-bit (x86), create this folder:
C:\Windows\System32\config\systemprofile\Desktop

Tags:

C# | Excel

MDX Query in C#

by 17. October 2011 08:46

 

Requires the AdomdClient, which is included in Microsoft SQL Server 2008 Feature Pack, October 2008, found here:

http://www.microsoft.com/downloads/details.aspx?FamilyId=228DE03F-3B5A-428A-923F-58A033D316E1&displaylang=en

Download "Microsoft ADOMD.NET " from the link above and after running msi file you will get
Microsoft.AnalysisServices.AdomdClient.dll under folder
C:\Program Files\Microsoft.NET\ADOMD.NET\100.

Tags:

C# | SSAS

ASP.Net Security Issue FormsAuthentication.Authenticate Always Returns false

by 14. October 2011 09:42

I was trying to create a custom authentication screen without using any of the standard ASP.Net security controls (i.e. Login control).  So, I created my custom form and was calling the System.Web.Security.FormsAuthentication.Authenticate(UserName, Password) method.  However, it was always returning false and in fact did not appear to even be hitting my SQL database (which contained the security) as the failed login attempts, etc. were all unaltered.  Furthermore, I changed my connection string to be a bogus reference and the Authenticate still simple returned false (I was expecting it to error).  I then found out that the System.Web.Security.FormsAuthentication.Authenticate(UserName, Password) method is for user information stored in the web.config file.  Instead, I used the System.Web.Security.Membership.ValidateUser(UserName, Password) method which is for the user information stored in the SQL database.

NOTE: When doing this I also then set the authorization cookie by calling:

System.Web.Security.FormsAuthentication.SetAuthCookie(UserName, true);

Here is some sample code:

static public string Login(string UserName, string Password)
{
  if (System.Web.Security.Membership.ValidateUser(UserName, Password))
  {
    System.Web.Security.FormsAuthentication.SetAuthCookie(UserName, true);
    return "1|" + DateTime.Now.ToString();
  }
  else
    return "0|Login failed!";
}

Tags:

ASP.Net | C#

ASP.Net WCF Data Services Error Hosting on Multiple Environments

by 25. September 2011 16:25

I encountered an error when attempting to access a WCF Data Service from my hosted web site.  This error did not occur when running the service on my local development PC.  This is the error I received: "This collection already contains an address with scheme http.  There can be at most one address pr scheme in this collection. Parameter name: item"  To resolve this error my web.config required and additional entry to provide the host name as shown here.

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
      <baseAddressPrefixFilters>
        <add prefix="http://mydomain.com" />
      </baseAddressPrefixFilters>
  </serviceHostingEnvironment>
</system.serviceModel>

Tags:

C#

C# Code to Get AD Members of a Security Group

by 15. September 2011 09:57

This method will accept a domain name and security group name and return all the AD members of that group.

using System.Collections.Generic;
using System.DirectoryServices;

namespace AdReader
{
  class Program
  {
    static void Main(string[] args)
    {
      List users = GetGroupMembers("domainname.com", "security group name");
      foreach (DirectoryEntry user in users)
      {
        System.Diagnostics.Debug.WriteLine(user.Name.Replace("CN=", ""));
      }
    }
    /// Gets a list of members in the specified group.        
    public static List GetGroupMembers(string domain, string groupName)
    {
      List users = new List();
      string filter = string.Format("(&(ObjectClass={0})(sAMAccountName={1}))", "group", groupName); // principal);            
      string[] properties = new string[] { "fullname" };
      DirectoryEntry adRoot = new DirectoryEntry("LDAP://" + domain, null, null, AuthenticationTypes.Secure);
      DirectorySearcher searcher = new DirectorySearcher(adRoot);
      searcher.SearchScope = SearchScope.Subtree;
      searcher.ReferralChasing = ReferralChasingOption.All;
      searcher.PropertiesToLoad.AddRange(properties);
      searcher.Filter = filter;
      SearchResult result = searcher.FindOne();
      if (result != null)
      {
        DirectoryEntry directoryEntry = result.GetDirectoryEntry();
        foreach (object dn in directoryEntry.Properties["member"])
        {
          DirectoryEntry member = new DirectoryEntry("LDAP://" + dn);
          //Add users from other groups within this group (only go 1 level deep).      
          if (!IsGroup(member))
          {
            users.Add(member);
          }
        }
      }
      return users;
    }
    /// Determine whether the object is a group.        
    private static bool IsGroup(DirectoryEntry de)
    {
      return de.Properties["objectClass"][1].ToString() == "group";
    }
  }
}

Tags:

C#

C# Code to Extract Binary Data from SQL and Save to Disk File

by 14. September 2011 14:24

This code will allow a simple SQL connection to select a single record with binary data in image column and save it as a file on the local disk.

string SQL = "select [FileData] from [MyTable] where [RecordID] = 1";
string cnString = @"Data Source=Server\Instance,Port;Initial Catalog=DB;Integrated Security=True;";
SqlConnection cn = new SqlConnection(cnString);
SqlCommand cmd = new SqlCommand(SQL, cn);
cn.Open();
byte[] byt = (byte[])cmd.ExecuteScalar();
FileStream fs = new FileStream(@"c:\temp\tempfile.txt"
  , FileMode.CreateNew, FileAccess.Write);
fs.Write(byt, 0, byt.Length);
fs.Flush();
fs.Close();

 

 

Tags:

C#

MDX CellSetGrid Source Code - Browse SSAS Cube

by 2. September 2011 08:38

This is a C# .Net framework 2.0 based custom web control that allows dynamic navigation of SSAS cube through a standard Asp.Net web page using the Microsoft.AnalysisServices.AdomdClient for data access.  To use it in Visual Studio, create a new solution and include the attached CellsetGrid project.  Then add a new file based web site and reference the CellsetGrid project from the web site.  Then drag the "CellSetGrid2" custom control onto the web page and set the ConnectionString and Cube properties.  ConnectionString will need at a minimum "Data Source=ServerName\InstanceName;Catalog=DatabaseName;".  Below is a screen shot of the control in action.

 

 

 

Tags:

C# | SSAS

C# Utility to Read Exif Image Data

by 28. August 2011 17:05

The below code will represents a utility class that makes it easier to get Exif data from images.

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using System.Linq;

namespace ImageProperties
{
  class ExifUtil
  {

    // Sample usage:
    // ExifUtil.EXIFReader exif = new ExifUtil.EXIFReader(@"c:\pathtoimage.jpg");
    // Console.WriteLine(exif[ExifUtil.PropertyTagId.EquipMake].ToString());
    // Console.WriteLine(exif[ExifUtil.PropertyTagId.EquipModel].ToString());

    public enum PropertyTagId
    {
      GpsVer = 0x0000,
      GpsLatitudeRef = 0x0001,
      GpsLatitude = 0x0002,
      GpsLongitudeRef = 0x0003,
      GpsLongitude = 0x0004,
      GpsAltitudeRef = 0x0005,
      GpsAltitude = 0x0006,
      GpsGpsTime = 0x0007,
      GpsGpsSatellites = 0x0008,
      GpsGpsStatus = 0x0009,
      GpsGpsMeasureMode = 0x000A,
      GpsGpsDop = 0x000B,
      GpsSpeedRef = 0x000C,
      GpsSpeed = 0x000D,
      GpsTrackRef = 0x000E,
      GpsTrack = 0x000F,
      GpsImgDirRef = 0x0010,
      GpsImgDir = 0x0011,
      GpsMapDatum = 0x0012,
      GpsDestLatRef = 0x0013,
      GpsDestLat = 0x0014,
      GpsDestLongRef = 0x0015,
      GpsDestLong = 0x0016,
      GpsDestBearRef = 0x0017,
      GpsDestBear = 0x0018,
      GpsDestDistRef = 0x0019,
      GpsDestDist = 0x001A,
      NewSubfileType = 0x00FE,
      SubfileType = 0x00FF,
      ImageWidth = 0x0100,
      ImageHeight = 0x0101,
      BitsPerSample = 0x0102,
      Compression = 0x0103,
      PhotometricInterp = 0x0106,
      ThreshHolding = 0x0107,
      CellWidth = 0x0108,
      CellHeight = 0x0109,
      FillOrder = 0x010A,
      DocumentName = 0x010D,
      ImageDescription = 0x010E,
      EquipMake = 0x010F,
      EquipModel = 0x0110,
      StripOffsets = 0x0111,
      Orientation = 0x0112,
      SamplesPerPixel = 0x0115,
      RowsPerStrip = 0x0116,
      StripBytesCount = 0x0117,
      MinSampleValue = 0x0118,
      MaxSampleValue = 0x0119,
      XResolution = 0x011A,
      YResolution = 0x011B,
      PlanarConfig = 0x011C,
      PageName = 0x011D,
      XPosition = 0x011E,
      YPosition = 0x011F,
      FreeOffset = 0x0120,
      FreeByteCounts = 0x0121,
      GrayResponseUnit = 0x0122,
      GrayResponseCurve = 0x0123,
      T4Option = 0x0124,
      T6Option = 0x0125,
      ResolutionUnit = 0x0128,
      PageNumber = 0x0129,
      TransferFunction = 0x012D,
      SoftwareUsed = 0x0131,
      DateTime = 0x0132,
      Artist = 0x013B,
      HostComputer = 0x013C,
      Predictor = 0x013D,
      WhitePoint = 0x013E,
      PrimaryChromaticities = 0x013F,
      ColorMap = 0x0140,
      HalftoneHints = 0x0141,
      TileWidth = 0x0142,
      TileLength = 0x0143,
      TileOffset = 0x0144,
      TileByteCounts = 0x0145,
      InkSet = 0x014C,
      InkNames = 0x014D,
      NumberOfInks = 0x014E,
      DotRange = 0x0150,
      TargetPrinter = 0x0151,
      ExtraSamples = 0x0152,
      SampleFormat = 0x0153,
      SMinSampleValue = 0x0154,
      SMaxSampleValue = 0x0155,
      TransferRange = 0x0156,
      JPEGProc = 0x0200,
      JPEGInterFormat = 0x0201,
      JPEGInterLength = 0x0202,
      JPEGRestartInterval = 0x0203,
      JPEGLosslessPredictors = 0x0205,
      JPEGPointTransforms = 0x0206,
      JPEGQTables = 0x0207,
      JPEGDCTables = 0x0208,
      JPEGACTables = 0x0209,
      YCbCrCoefficients = 0x0211,
      YCbCrSubsampling = 0x0212,
      YCbCrPositioning = 0x0213,
      REFBlackWhite = 0x0214,
      Gamma = 0x0301,
      ICCProfileDescriptor = 0x0302,
      SRGBRenderingIntent = 0x0303,
      ImageTitle = 0x0320,
      ResolutionXUnit = 0x5001,
      ResolutionYUnit = 0x5002,
      ResolutionXLengthUnit = 0x5003,
      ResolutionYLengthUnit = 0x5004,
      PrintFlags = 0x5005,
      PrintFlagsVersion = 0x5006,
      PrintFlagsCrop = 0x5007,
      PrintFlagsBleedWidth = 0x5008,
      PrintFlagsBleedWidthScale = 0x5009,
      HalftoneLPI = 0x500A,
      HalftoneLPIUnit = 0x500B,
      HalftoneDegree = 0x500C,
      HalftoneShape = 0x500D,
      HalftoneMisc = 0x500E,
      HalftoneScreen = 0x500F,
      JPEGQuality = 0x5010,
      GridSize = 0x5011,
      ThumbnailFormat = 0x5012,
      ThumbnailWidth = 0x5013,
      ThumbnailHeight = 0x5014,
      ThumbnailColorDepth = 0x5015,
      ThumbnailPlanes = 0x5016,
      ThumbnailRawBytes = 0x5017,
      ThumbnailSize = 0x5018,
      ThumbnailCompressedSize = 0x5019,
      ColorTransferFunction = 0x501A,
      ThumbnailData = 0x501B,
      ThumbnailImageWidth = 0x5020,
      ThumbnailImageHeight = 0x5021,
      ThumbnailBitsPerSample = 0x5022,
      ThumbnailCompression = 0x5023,
      ThumbnailPhotometricInterp = 0x5024,
      ThumbnailImageDescription = 0x5025,
      ThumbnailEquipMake = 0x5026,
      ThumbnailEquipModel = 0x5027,
      ThumbnailStripOffsets = 0x5028,
      ThumbnailOrientation = 0x5029,
      ThumbnailSamplesPerPixel = 0x502A,
      ThumbnailRowsPerStrip = 0x502B,
      ThumbnailStripBytesCount = 0x502C,
      ThumbnailResolutionX = 0x502D,
      ThumbnailResolutionY = 0x502E,
      ThumbnailPlanarConfig = 0x502F,
      ThumbnailResolutionUnit = 0x5030,
      ThumbnailTransferFunction = 0x5031,
      ThumbnailSoftwareUsed = 0x5032,
      ThumbnailDateTime = 0x5033,
      ThumbnailArtist = 0x5034,
      ThumbnailWhitePoint = 0x5035,
      ThumbnailPrimaryChromaticities = 0x5036,
      ThumbnailYCbCrCoefficients = 0x5037,
      ThumbnailYCbCrSubsampling = 0x5038,
      ThumbnailYCbCrPositioning = 0x5039,
      ThumbnailRefBlackWhite = 0x503A,
      ThumbnailCopyRight = 0x503B,
      LuminanceTable = 0x5090,
      ChrominanceTable = 0x5091,
      FrameDelay = 0x5100,
      LoopCount = 0x5101,
      GlobalPalette = 0x5102,
      IndexBackground = 0x5103,
      IndexTransparent = 0x5104,
      PixelUnit = 0x5110,
      PixelPerUnitX = 0x5111,
      PixelPerUnitY = 0x5112,
      PaletteHistogram = 0x5113,
      Copyright = 0x8298,
      ExifExposureTime = 0x829A,
      ExifFNumber = 0x829D,
      ExifIFD = 0x8769,
      ICCProfile = 0x8773,
      ExifExposureProg = 0x8822,
      ExifSpectralSense = 0x8824,
      GpsIFD = 0x8825,
      ExifISOSpeed = 0x8827,
      ExifOECF = 0x8828,
      ExifVer = 0x9000,
      ExifDTOrig = 0x9003,
      ExifDTDigitized = 0x9004,
      ExifCompConfig = 0x9101,
      ExifCompBPP = 0x9102,
      ExifShutterSpeed = 0x9201,
      ExifAperture = 0x9202,
      ExifBrightness = 0x9203,
      ExifExposureBias = 0x9204,
      ExifMaxAperture = 0x9205,
      ExifSubjectDist = 0x9206,
      ExifMeteringMode = 0x9207,
      ExifLightSource = 0x9208,
      ExifFlash = 0x9209,
      ExifFocalLength = 0x920A,
      ExifMakerNote = 0x927C,
      ExifUserComment = 0x9286,
      ExifDTSubsec = 0x9290,
      ExifDTOrigSS = 0x9291,
      ExifDTDigSS = 0x9292,
      ExifFPXVer = 0xA000,
      ExifColorSpace = 0xA001,
      ExifPixXDim = 0xA002,
      ExifPixYDim = 0xA003,
      ExifRelatedWav = 0xA004,
      ExifInterop = 0xA005,
      ExifFlashEnergy = 0xA20B,
      ExifSpatialFR = 0xA20C,
      ExifFocalXRes = 0xA20E,
      ExifFocalYRes = 0xA20F,
      ExifFocalResUnit = 0xA210,
      ExifSubjectLoc = 0xA214,
      ExifExposureIndex = 0xA215,
      ExifSensingMethod = 0xA217,
      ExifFileSource = 0xA300,
      ExifSceneType = 0xA301,
      ExifCfaPattern = 0xA302
    }

    public enum PropertyTagType
    {
      PixelFormat4bppIndexed = 0,
      Byte = 1,
      ASCII = 2,
      Short = 3,
      Long = 4,
      Rational = 5,
      Undefined = 7,
      SLONG = 9,
      SRational = 10
    }

    public class Fraction
    {
      #region Class constructor

      public Fraction(int numerator, int denumerator)
      {
        Numerator = numerator;
        Denumerator = denumerator;
      }

      public Fraction(uint numerator, uint denumerator)
      {
        Numerator = Convert.ToInt32(numerator);
        Denumerator = Convert.ToInt32(denumerator);
      }

      public Fraction(int numerator)
      {
        Numerator = numerator;
        Denumerator = 1;
      }

      #endregion

      #region Numerator

      private int numerator;
      public int Numerator
      {
        get
        {
          return numerator;
        }
        set
        {
          numerator = value;
        }
      }

      #endregion

      #region Denumerator

      private int denumerator;
      public int Denumerator
      {
        get
        {
          return denumerator;
        }
        set
        {
          denumerator = value;
        }
      }

      #endregion

      #region ToString override

      public override string ToString()
      {
        if (Denumerator == 1)
          return String.Format("{0}", Numerator);
        else
          return String.Format("{0}/{1}", Numerator, Denumerator);
      }


      #endregion
    }

    public class PropertyTagValue
    {
      public static object GetValueObject(PropertyItem property)
      {
        if (property == null)
          return null;
        switch ((PropertyTagType)property.Type)
        {
          //ASCII
          case PropertyTagType.ASCII:
            ASCIIEncoding encoding = new ASCIIEncoding();
            return encoding.GetString(property.Value, 0, property.Len - 1);
          //BYTE
          case PropertyTagType.Byte:
            if (property.Len == 1)
              return property.Value[0];
            else
              return property.Value;
          //LONG
          case PropertyTagType.Long:
            uint[] resultLong = new uint[property.Len / 4];
            for (int i = 0; i < resultLong.Length; i++)
              resultLong[i] = BitConverter.ToUInt32(property.Value, i * 4);
            if (resultLong.Length == 1)
              return resultLong[0];
            else
              return resultLong;
          //SHORT
          case PropertyTagType.Short:
            ushort[] resultShort = new ushort[property.Len / 2];
            for (int i = 0; i < resultShort.Length; i++)
              resultShort[i] = BitConverter.ToUInt16(property.Value, i * 2);
            if (resultShort.Length == 1)
              return resultShort[0];
            else
              return resultShort;
          //SLONG
          case PropertyTagType.SLONG:
            int[] resultSLong = new int[property.Len / 4];
            for (int i = 0; i < resultSLong.Length; i++)
              resultSLong[i] = BitConverter.ToInt32(property.Value, i * 4);
            if (resultSLong.Length == 1)
              return resultSLong[0];
            else
              return resultSLong;
          //RATIONAL
          case PropertyTagType.Rational:
            Fraction[] resultRational = new Fraction[property.Len / 8];
            uint uNumerator;
            uint uDenumerator;
            for (int i = 0; i < resultRational.Length; i++)
            {
              uNumerator = BitConverter.ToUInt32(property.Value, i * 8);
              uDenumerator = BitConverter.ToUInt32(property.Value, i * 8 + 4);
              resultRational[i] = new Fraction(uNumerator, uDenumerator);
            }
            if (resultRational.Length == 1)
              return resultRational[0];
            else
              return resultRational;
          //SRATIONAL
          case PropertyTagType.SRational:
            Fraction[] resultSRational = new Fraction[property.Len / 8];
            int sNumerator;
            int sDenumerator;
            for (int i = 0; i < resultSRational.Length; i++)
            {
              sNumerator = BitConverter.ToInt32(property.Value, i * 8);
              sDenumerator = BitConverter.ToInt32(property.Value, i * 8 + 4);
              resultSRational[i] = new Fraction(sNumerator, sDenumerator);
            }
            if (resultSRational.Length == 1)
              return resultSRational[0];
            else
              return resultSRational;
          //UNDEFINE
          default:
            if (property.Len == 1)
              return property.Value[0];
            else
              return property.Value;
        }
      }
    }

    public class EXIFReader
    {
      #region EXIFReader constructors

      public EXIFReader(Image image)
      {
        this.image = image;
        props = image.PropertyItems;
      }

      public EXIFReader(string path)
      {
        using (FileStream fs = new FileStream(path, FileMode.Open))
        {
          this.image = Image.FromStream(fs);
          props = image.PropertyItems;
        }
      }

      public EXIFReader(Stream stream)
      {
        this.image = Image.FromStream(stream);
        props = image.PropertyItems;
      }

      #endregion

      #region Image

      public Image image;
      private PropertyItem[] props;

      #endregion

      #region EXIF property indexers

      public object this[int Id]
      {
        get
        {
          try
          {
            PropertyItem property = props.Where(x => x.Id.ToString().Equals(Id.ToString())).FirstOrDefault();
            return PropertyTagValue.GetValueObject(property);
          }
          catch
          {
            return null;
          }
        }
      }

      public object this[PropertyTagId TagId]
      {
        get
        {
          try
          {
            PropertyItem property = props.Where(x => x.Id.ToString().Equals(((int)TagId).ToString())).FirstOrDefault();
            return PropertyTagValue.GetValueObject(property);
          }
          catch
          {
            return null;
          }
        }
      }

      #endregion
    }

  }
}

Tags:

C#

Convert C# DataTable to Delimited File

by 22. August 2011 16:11

 

public static DataTable GetDataTableFromCsv(string FilePath)
{
  return GetDataTableFromDelim(FilePath, ",");
}
public static DataTable GetDataTableFromTab(string FilePath)
{
  return GetDataTableFromDelim(FilePath, @"\t");
}
public static DataTable GetDataTableFromDelim(string FilePath, string Delim)
{
  DataTable tbl = new DataTable();
  string CsvData = string.Empty;
  CsvData = File.ReadAllText(FilePath);
  bool firstRow = true;
  foreach (string row in CsvData.Split("\n".ToCharArray()))
  {
    DataRow dr = tbl.NewRow();
    System.Text.RegularExpressions.RegexOptions options = (
        System.Text.RegularExpressions.RegexOptions.IgnorePatternWhitespace
      | System.Text.RegularExpressions.RegexOptions.Multiline
      | System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    Regex reg = new Regex(Delim 
      + @"(?=(?:[^\""]*\""[^\""]*\"")*(?![^\""]*\""))", options);
    var csvArray = reg.Split(row.Replace("\n", "").Replace("\r", ""));
    for (int i = 0; i < csvArray.Length; i++)
    {
      csvArray[i] = csvArray[i].Replace("\"\"", "");
      if (firstRow)
        tbl.Columns.Add(new DataColumn() { ColumnName = csvArray[i] });
      else
        dr[i] = csvArray[i];
      Console.WriteLine(csvArray[i]);
    }
    if (!firstRow && !dr[0].ToString().Length.Equals(0)) tbl.Rows.Add(dr);
    firstRow = false;
  }
  return tbl;
}

private static string DelimTextFromTable(DataTable tbl, string delim)
{
  var sb = new StringBuilder();
  sb.AppendLine(string.Join(delim,
    tbl.Columns.Cast<DataColumn>().Select(arg => arg.ColumnName)));
  foreach (DataRow dataRow in tbl.Rows)
    sb.AppendLine(string.Join(delim,
      dataRow.ItemArray.Select(arg => arg.ToString())));
  return sb.ToString();
}

Tags:

C#

Create a Simple Windows Service to Send Daily Email with Dynamically Created .CSV Attachment

by 17. August 2011 10:28

The sample code below shows how to setup a simple Windows service that will send a daily email with a dynamically generated .CSV file (built by querying a SQL database).  After you compile the program you can using these commands to setup and delete the service (to update the service you will delete and re-install):

  • sc create MyServiceName binpath= "C:\PathToExecutable\Executable.exe"
  • sc delete MyServiceName
using System;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Net.Mail;
using System.ServiceProcess;
using System.Text;

namespace CrmRatesheetDistributionListEmailer
{
  public partial class Emailer : ServiceBase
  {
    public Emailer()
    {
      InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
      BackgroundWorker wkr = new BackgroundWorker();
      wkr.DoWork += DailyEmailManager;
      wkr.RunWorkerAsync();
    }

    private void DailyEmailManager(object sender, DoWorkEventArgs e)
    {
      DateTime lastRun = DateTime.MinValue;
      do
      {
        if (lastRun.DayOfYear.Equals(DateTime.Today.DayOfYear))
        {
          System.Threading.Thread.Sleep(60 * 1000);
          continue;
        }
        lastRun = DateTime.Today;
        SmtpClient mail = new SmtpClient("mailrelay.mydomain.com");
        MailMessage msg = new MailMessage("fromme@mydomain.com", "toyou@yourdomain.com", "Sample Daily Email", "This is a sample windows service that will send a daily email.");
        msg.CC.Add(new MailAddress("someoneelse@yourdomain.com"));
        msg.Attachments.Add(new Attachment(GetAttachment()));
        mail.Send(msg);
      } while (true);
    }

    private string GetAttachment()
    {
      SqlConnection cn = new SqlConnection("Data Source=ServerName;Initial Catalog=DatabaseName;Integrated Security=true;");
      SqlCommand cmd = new SqlCommand("select * from SomeTable where SomeCritera = true", cn);
      DataTable tbl = new DataTable();
      SqlDataAdapter da = new SqlDataAdapter(cmd);
      da.Fill(tbl);
      string fileName = "c:\\temp\\SomeFileName.csv";
      System.IO.StreamWriter file = new System.IO.StreamWriter(fileName);
      file.Write(TableToCSV(tbl));
      file.Close();
      return fileName;
    }

    private static string TableToCSV(DataTable table)
    {
      var result = new StringBuilder();
      for (int i = 0; i < table.Columns.Count; i++)
      {
        result.Append(table.Columns[i].ColumnName);
        result.Append(i == table.Columns.Count - 1 ? "\n" : ",");
      }
      foreach (DataRow row in table.Rows)
      {
        for (int i = 0; i < table.Columns.Count; i++)
        {
          result.Append(row[i].ToString());
          result.Append(i == table.Columns.Count - 1 ? "\n" : ",");
        }
      } return result.ToString();
    }

    protected override void OnStop()
    {
    }
  }
}

Tags:

C#

Get User that Initiated Task Change Event on a Workflow Task in Sharepoint

by 17. June 2011 11:13

This topic covers Sharepoint workflow tasks.  Specifically, the how to get the user account that triggered the workflow event.  By using the typical CurrentUser method on the Web object you will typically get the SHAREPOINT\system account rather than the actual account of the user that initiated the event.  Instead you can use the OriginatorUser method of the Workflowproperties as shown below.

// In both cases below you will typically get "SHAREPOINT\system"
Workflowproperties.web.CurrentUser;
// or
SPContext.Current.Web.CurrentUser;

// To get the acutal user that initiated task change event use this:
Workflowproperties.OriginatorUser

 

Tags:

C# | Sharepoint

Update Sharepoint Task Item inside Workflow Causes Item to be Indefinitely Locked by Workflow

by 17. June 2011 10:31

This topic covers updating a Sharepoint workflow task item, inside of a workflow event.  Sometimes performing an update to the item inside the workflow event will cause the item to be seen as indefinitely locked by the workflow in which case future attempts to update the same item (either inside a workflow event or by a user attempting to edi the item directly through the Sharepoint front end) will result in this error: "This task is currently locked by a running workflow and cannot be edited.". 

Typically, this will happen if you use the basic Update method of the item object (as shown in sample code below).  However, you should instead use the SystemUpdate method along with the explicit setting of the WorkflowVersion field value to 1 (as shown in sample code below).

/* You have to include the following two lines before the call to item.SystemUpdate()   
* to avoid this error:    
* "This task is currently locked by a running workflow and cannot be edited."   
* For details see:    
* http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splistitem.update%28v=office.12%29.aspx   
*/
web.AllowUnsafeUpdates = true; 
// You have to include this line  
item[SPBuiltInFieldId.WorkflowVersion] = 1;  
item.SystemUpdate(false);  // Don't use: item.Update(); 
//

Tags:

C# | Sharepoint