How to allow excel data modification in manual as well as programmatically? - c#

I am using C# windows application for Excel data add/update. I had added Microsoft.Office.Interop.Excel reference(Reference -> Right Click -> Add Reference -> COM -> Type Libraries -> Microsoft Excel 1X.0 Object Libraries). On my form, I have one panel control panel1, one List-box lstSamples and two button btnAddSample, btnFormatWorksheet.
My sample code is as below:
using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public partial class Form1 : Form
{
Microsoft.Office.Interop.Excel.Application excelApp;
Workbook excelWorkBook;
Worksheet excelWorkSheet;
public Form1()
{
InitializeComponent();
LoadExcelFile();
}
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private void LoadExcelFile()
{
excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Visible = true;
excelApp.ScreenUpdating = true;
excelApp.EnableAutoComplete = false;
excelWorkBook = excelApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
IntPtr excelHwnd = new IntPtr(excelApp.Application.Hwnd);
SetParent(excelHwnd, panel1.Handle);
}
private void btnAddSample_Click(object sender, EventArgs e)
{
excelWorkSheet = (Worksheet)excelWorkBook.Worksheets.get_Item(1);
int lastUsedRow = excelWorkSheet.UsedRange.Rows.Count;
excelWorkSheet.Cells[lastUsedRow + 1, 1] = lstSamples.SelectedItem.ToString();
lstSamples.Items.Remove(lstSamples.SelectedItem);
}
private void btnFormatWorksheet_Click(object sender, EventArgs e)
{
Range chartRange;
excelWorkSheet = (Worksheet)excelWorkBook.Worksheets.get_Item(1);
chartRange = excelWorkSheet.get_Range("b2", "e9");
chartRange.BorderAround(XlLineStyle.xlContinuous,
XlBorderWeight.xlMedium, XlColorIndex.xlColorIndexAutomatic,
XlColorIndex.xlColorIndexAutomatic);
}
}
Please follow the steps as I mentioned 1. Run the application and add data in "A1" cell (Which is of string type) 2. Again add some data in "A2" cell and Press enter 3. Select one item from lstSamples listbox and click on btnAddSample (Result is like selected item will get added into "A3" cell 4. Try to modify "A1" or "A2" cell data. (Here lstSample is having items of string type like Test1, Test2, Test3,....). If you are able to edit cells then click on btnFormatWorksheet then try to edit any cell.

Why are you referencing the COM DLL? You should be referencing the .Net PIA's - the Primary Interop Assemblies in this location, via the .Net tab in the References window and browse to:
C:\Program Files (x86)\Microsoft Visual Studio [version]\Visual Studio Tools for Office\PIA\Office[version]\Microsoft.Office.Interop.Excel.dll
Only for unit testing do you reference the COM one. See my answer here and how I originally worked it out. It's easy to get confused because in Solution Explorer they are both called the same thing!
If that doesn't work, I originally put this as an answer to save other peoples time being wasted.
Both Ahmed and I cannot reproduce the problem you described with the code you have provided.
See I typed in cells A1 and A2, then I selected an item in the list and clicked the button. Then I select the cell A2 and type Editable.
ps If you can provide the steps to reproduce I'll be happy to take another look at it.
UPDATE:
Your revised steps to reproduce the problem are incorrect, it works for me:
UPDATE 2:
Check if the message pump filters are causing the focus to go to another cell/control:
Excel CustomTaskPane with WebBrowser control - keyboard/focus issues

Related

Microsoft.Office.Interop.Excel add radio button to worksheet

I keep looking for examples on how to add a radio button to an Excel worksheet programmatically but cannot get a straight answer. I've tried using Microsoft.Office.Interop.Excel and Microsoft.Office.Tools.Excel but neither have worked. The system I am working on already has Microsoft.Office.Interop.Excel as a reference so unless there are any objections to using this assembly, this would be my preference.
//propertyWorkSheet is a Microsoft.Office.Interop.Excel worksheet
Microsoft.Office.Tools.Excel.Application xlApp = new Excel.Application();
Microsoft.Office.Tools.Excel.Worksheet worksheet = (Microsoft.Office.Tools.Excel.Worksheet)propertyWorksheet;
Microsoft.Office.Tools.Excel.Range selection = worksheet.get_Range("A12:A12", "A12:A12");
Microsoft.Office.Tools.Excel.Controls.Button button = new Microsoft.Office.Tools.Excel.Controls.Button();
worksheet.Controls.AddControl(button, selection, "Button");
Did some more digging and got to this with my code and it worked.
Microsoft.Office.Interop.Excel.Buttons buttons = propertyWorksheet.Buttons(System.Reflection.Missing.Value) as Microsoft.Office.Interop.Excel.Buttons;
Microsoft.Office.Interop.Excel.Button button = buttons.Add(33, 33, 33, 33);
button.Caption = "Test BUTTON";

Open a second Form with a textbox

i open about my Button "ProtokollToolStripMenuItemClick" my second Form! The name of the second Form is INPUTBOX! This second Form has two text boxes and one Button! Now i would like to put in my name and my mobile phone number in the two text boxes and close the window with my button. This two entries i would like to put down in my excel application.(But i donĀ“t now how to get the text box entries). How can i do this?
public partial class MainForm
{
public void ProtokollToolStripMenuItemClick(object sender, EventArgs e)
{
INPUTBOX _Input = new INPUTBOX();
_Input.Show();
//Here I want to put in my new code
//Declaration
Excel.Application ExcelApplication;
Excel._Workbook ExcelWorkbook;
Excel._Worksheet ExcelWorksheet;
try
{
//Start Excel
ExcelApplication = new Excel.Application();
ExcelApplication.Visible = true;
//New Workbook
ExcelWorkbook = (Excel._Workbook)(ExcelApplication.Workbooks.Add(Missing.Value));
ExcelWorksheet = (Excel._Worksheet)ExcelWorkbook.ActiveSheet;
//et cetera
Open the input box with ShowDialog instead of Show, to ensure that your code pauses until the window has been closed.
In your INPUTBOX, create a public property for each of the values you want to return.
In your button click handler, copy the values from the text boxes to the public properties.
Afterwards, in the code shown in your question, you can access the values by accessing _input.NameOfTheNewProperty.
Supposedely you have named your controls txtName and txtPhone you may access them using the following from the calling form.
_Input.txtName.Text
_Input.txtPhone.Text

Copy/Paste a listobject in excel lose the attached events

Let's create a ListObject and attach an event on it as msdn explain here: https://msdn.microsoft.com/en-us/library/eyfs6478.aspx
The code
In an application-level addin, code will look like above:
Worksheet worksheet = Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]);
Excel.Range cell = worksheet.Range["$A$1:$D$4"];
ListObject list1 = worksheet.Controls.AddListObject(cell, "list1");
list1.Selected += list1_SelectedDeselected;
list1.Deselected += list1_SelectedDeselected;
With something like that to see the triggered events :
private void list1_SelectedDeselected(Excel.Range Target)
{
Worksheet worksheet = Globals.Factory.GetVstoObject(Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]);
Excel.Range cell = worksheet.Range["$A$6"];
if (cell.Value2 == "foo")
{
cell.Value2 = "bar";
}
else
{
cell.Value2 = "foo";
}
}
Strange behavior
If you run this code within a add-in in excel, you'll see this and that
If you cut/paste this table within the same worksheet, every attached events will be triggered.
But if you cut/paste into another sheet, the events will not be attached anymore to the ListObject.
Are there a reason I don't know for this unpredictable behavior?
You need to use another VSTO object to subscribe to the events anew. The GetVstoObject should be used to get a new Worksheet object.

Excel Interop right to left document

I created a new Excel file with C#.
When I open the document all the worksheets are align right to left.
How can I align the worksheet/workbook/window to display left to right grammatically?
Sub leftToRight()
Application.DefaultSheetDirection = xlLTR
ActiveSheet.DisplayRightToLeft = False
End Sub
You can also change the setting through Tools->Options->International. Note that you need to set/unset the Checkbox "View current sheet right-to-left" to change currently open sheets.
Edit: Sorry I accidentally interpreted your question as VBA.
Here is a c# Solution:
Excel.Application xlApp = new Excel.Application();
xlApp.Visible = true;
xlApp.Workbooks.Add(System.Type.Missing);
Excel.Worksheet active = (Excel.Worksheet)xlApp.ActiveSheet;
xlApp.DefaultSheetDirection = (int)Excel.Constants.xlLTR; //or xlRTL
active.DisplayRightToLeft = false;
I would like to introduce my implementation of this feature after i used marg concept and changed it to the right syntax for me:
public void SetWorksheetDirection(Application excel, bool isRTL)
{
Worksheet active = (Worksheet)excel.ActiveSheet;
if (isRTL)
excel.DefaultSheetDirection = (int)XlDirection.xlToRight;
else
excel.DefaultSheetDirection = (int)XlDirection.xlToLeft;
active.DisplayRightToLeft = isRTL;
}
Do this one time to change the default direction:
Alt+F11 to open the VBA editor
Ctrl+G to open the Immediate window
in the Immediate window type Application.DefaultSheetDirection = xlLTR and press Enter
Alt+Q to close the VBA editor
create a new workbook to test it
If you just wanted to organize some of the columns, you could use a line like this:
oWS.Range["A1:B2000"].HorizontalAlignment = Microsoft.Office.Interop.Excel.Constants.xlLeft;

How can I use the Windows look'n'feel for a system tray context menu?

I'm working with a NotifyIcon and ContextMenuStrip, I don't want to use the default menu look and feel which is shipped out of the box with this control which is different to Windows (Vista in my case) by using contextMenu.RenderMode = ToolStripRenderMode.ManagerRenderMode or contextMenu.RenderMode = ToolStripRenderMode.Professional:
I don't want this using contextMenu.RenderMode = ToolStripRenderMode.System:
I just want to use the standard, normal Windows "look and feel" as seen in countless, probably non-.net applications *grumble*:
Any ideas guys on how to achieve this?
On Vista, it renders correctly (i.e., the same way DropBox renders on my machine) when using all the defaults.
Here's a sample program that works for me. Try it, and if it doesn't render correctly for you, try uncommenting the two commented lines.
using System;
using System.Windows.Forms;
using System.Drawing;
public class AC : ApplicationContext
{
NotifyIcon ni;
public void menu_Quit(Object sender, EventArgs args)
{
ni.Dispose();
ExitThread();
}
public AC()
{
ni = new NotifyIcon();
ni.Icon = SystemIcons.Information;
ContextMenu menu = new ContextMenu();
menu.MenuItems.Add("Quit", new EventHandler(menu_Quit));
ni.ContextMenu = menu;
ni.Visible = true;
}
public static void Main(string[] args)
{
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
AC ac = new AC();
Application.Run(ac);
}
}
For reference, this is how to get a notification icon with a Windows-styled context menu:
1) In the controls toolbox, right-click All Windows Forms > Choose Items
2) Tick ContextMenu > OK
3) Right-click All Windows Forms > Sort Items Alphabetically
4) Drag the new ContextMenu into the form designer
5) Right-click ContextMenu1 > Properties > Rename it to something memorable (for future reference, I've renamed mine to myNotifyIconContext)
6) In the Solution Explorer, expand Form1.cs (etc) > Double-click Form1.Designer.cs
7) Find your notification icon - it will look something like this:
//
// notifyIcon1
//
this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1;
this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon")));
this.notifyIcon1.Text = "My Notification Icon";
this.notifyIcon1.Visible = true;
Here, I previously had a ContextMenuStrip.
8) Change the first line of code to (or add):
this.notifyIcon1.ContextMenu = this.myNotifyIconContext;
et voila!

Categories

Resources