Wednesday, 14 September 2016

Disappearing TabPage Title Text when adding to a SplitContainer Panel

On a project we had a problem where TabPage title text would disappear when a TabPage was added to a SplitContainer Panel. For a while I did not know how to solve this issue because it was not obvious what was causing it.

disappearing-tab-headertitle-text-in-splitcontainer

After some research, it appeared to be a known Microsoft issue as described in this post: https://bytes.com/topic/c-sharp/answers/457492-tabpage-text-disapearing

However, I was not convinced this would be an ideal solution. I wanted something quick and simple. I ran a test and noticed when adding TabPages to the test SplitContainer, that the TabPage title did not disappear. Also the test did not contain a MenuStrip control, which the client app did.

Then I suspected the menu was causing the problem, because it was overlapping the TabPage title, and the title text was not disappearing at all.

To solve it, I simply added some padding to the SplitContainer panel, to push it below the MenuStrip in the client application. Here is some code.

SplitContainer1.Panel1.Padding = new Padding(0, 27, 0, 0); 

27 represents the default height in pixels of a MenuStrip, the top padding on the SplitContainer panel should then clear the menu and the title text will show.

Friday, 26 August 2016

Accessing Microsoft Excel without using Interop

In a recent project, the server we deployed to did not have Microsoft Office installed, it only had Microsoft Excel loaded for some reason.

We could not use the C# Microsoft Interop Services to access Excel, and it came up with the error "Could not load file or assembly 'Microsoft.Office.Interop.Excel', or one of its dependencies. The system cannot find the file specified."


Could not load Interop

After searching and not finding much about accessing Excel without using Interop, I stumbled upon an old post from decades ago about using Visual Basic and its CreateObject, GetType, InvokeMember and CallByName functions in the Interaction interface.

Such a godsend, after a few tests I was then able to access Excel through its COM component.


You can check Workbook member properties here: https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel._workbook_members.aspx


Here is some code to show the process to access the Excel COM Component, it may need adjusting for your own project.

using System.Windows.Forms;
using Microsoft.VisualBasic;
using System.Reflection;
using Microsoft.Office.Interop;

PrintDialog PrinterForm = new PrintDialog( );
string FileNamePath = "C:\\ExcelFile.xlsx";

// Create COM object to Excel Application.
Object XLApp = Interaction.CreateObject("Excel.Application");

// Get COM object Excel Workbooks interface.
XLApp.GetType().InvokeMember(
"Workbooks", BindingFlags.GetProperty | BindingFlags.Public, 
null, XLApp, null);

// Test getting Workbooks interface from XLApp COM Object.
Object XLWorkbooks = Interaction.CallByName(
XLApp, "Workbooks", Microsoft.VisualBasic.CallType.Get, null);

// Call Open method on Workbooks interface.
// Pass it the filename parameter.
// Excel COM object should then issue command to Excel.
// Excel to open the filename (xlsx).
Interaction.CallByName(XLWorkbooks, "Open", 
Microsoft.VisualBasic.CallType.Method, FileNamePath);

// Debug (Workbooks object).
// string WorkbooksString = XLWorkbooks.ToString();
// MessageBox.Show("WorkbooksString = [" + WorkbooksString + "]", "Debug");
// Show print form to user.
if (PrinterForm.ShowDialog() == DialogResult.OK)
{
// Cast XLWorkbooks to Workbooks collection.
Microsoft.Office.Interop.Excel.Workbooks XLWorkbooks2 = (Microsoft.Office.Interop.Excel.Workbooks)XLWorkbooks;

// Iterate Workbooks collection.
foreach (Microsoft.Office.Interop.Excel.Workbook XLWorkbook in XLWorkbooks2)
{
// Debug (XLWorkbook).
// MessageBox.Show("XLWorkbook String = [" + XLWorkbook.ToString() + "]", "Debug");
// Print workbook to user specified printer.
XLWorkbook.PrintOutEx(
Type.Missing, Type.Missing, Type.Missing, 
Type.Missing, printDialog.PrinterSettings.PrinterName);

// Close workbook.
XLWorkbook.Close(false);
}
}

// Close COM Excel.
Interaction.CallByName(
XLApp, "Quit", 
Microsoft.VisualBasic.CallType.Method, null);