![]() |
Desktop Development »
Selection Controls »
General
Beginner
License: The Code Project Open License (CPOL)
RefEdit Emulation for .NETBy pablleafA simple implementation of a ref edit control for .NET |
VB (VB9.0), .NET (.NET2.0), Office, Visual-Studio (VS2008), Dev
|
||||||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
When I originally posted this article it was simple Proof-Of-Concept article showing that a refedit control can be build to communicate between Excel and your .NET app. I spent some time this past week and developed a reusable UserControl.
To keep things fair, I want to say that not all the ideas in the control are mine. I found some useful tidbits here (MSDN Blog). Although this works, I could not get it to work in Excel 2003. Just changing the PIA references was not enough. It is tied to Office 2007 thru the RibbionUI.
After consolidating my work and using some of the techniques from the MSDN blog. I developed this UserControl that works with Excel 2003.

I started a project last year that required my .NET application to communicate with Excel. The project required that the user be able to select columns from a spreadsheet to be uploaded to SQL.
As everyone who has done Excel VBA programming, the refedit control is great! it allows users to select ranges from a spreadsheet thru the use of the mouse or keyboard.
With the introduction of .NET and VSTO, Microsoft did not release a refedit control. This meant that porting your beloved VBA code, that used a refedit control, to .NET was not going to happen so smoothly.
Like everyone else I hopped right onto Google's search engine and looked up RefEdit Controls for .NET. Guess what? Never found one and all the forums I visited said that Microsoft would not provide one because the RefEdit control is TIGHTLY integrated with Excel. All the examples I found said to us the InputBox. While this is a workaround, it shouldn't be the solution.
The user control consist of two components:
The user control also uses the 11.0 Interop assembly for Excel (Microsoft.Office.Interop.Excel)
After you have added the control to the toolbox. You simply drag it to any place on the form. At this time, the control is not functional it requires that you "connect" it to the spreadsheet it is talking to.
Me.Excel2003RefEdit1.Connection = xl
The connection property of the RefEdit control is of Type Excel.Application. This means that you will have to have the Excel Object instantiated on the form.
Dim xl As Microsoft.Office.Interop.Excel.Application
Private Sub Form2_Shown(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Me.Shown
xl = New Microsoft.Office.Interop.Excel.Application
xl.Workbooks.Add()
xl.Visible = True
Me.Excel2003RefEdit1.Connection = xl
Me.Excel2003RefEdit2.Connection = xl
End Sub
At this point, this is all the configuration required for the control to work. The rest happens inside the control.
Once a "connection" has been established with the spreadsheet. The control is functional. For the control to capture the cell selection in Excel, I created a method that captures the Excel Event. This method is fired when the user selects the refedit control.
Private Sub SinkEvents()
xlSheet = RefEditExcel.ActiveSheet
EventDel_SelectionChange = New Excel.DocEvents_SelectionChangeEventHandler(
AddressOf SelectionChange)
AddHandler xlSheet.SelectionChange, EventDel_SelectionChange
End Sub
Private Sub txtAddress_Enter(ByVal sender As Object,
ByVal e As System.EventArgs) Handles txtAddress.Enter
Call SinkEvents()
End Sub
The method that captures the excel range writes the value to the textbox. It requires the use of a delegate because of Cross Threading.
Delegate Sub WriteData(ByVal value As String)
Private Sub SelectionChange(ByVal Target As Excel.Range)
Call WriteHeader("'" & Target.Worksheet.Name & "'!" & Target.Address)
Call NAR(Target)
End Sub
Private Sub WriteHeader(ByVal value As String)
If Me.InvokeRequired Then
Me.Invoke(New WriteData(AddressOf WriteHeader), New Object() {value})
Else
Me.txtAddress.Text = value
End If
End Sub
Once the data is written, I make sure to destroy the Excel Reference. This is done using the NAR method.
Private Sub NAR(ByVal ComObj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(ComObj)
ComObj = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
Catch ex As Runtime.InteropServices.COMException
MessageBox.Show(ex.Message)
End Try
End Sub
When the user clicks out of the control, the control releases its handle on the Excel Event.
Private Sub UnSinkEvents()
RemoveHandler xlSheet.SelectionChange, EventDel_SelectionChange
End Sub
Private Sub txtAddress_Leave(ByVal sender As Object,
ByVal e As System.EventArgs) Handles txtAddress.Leave
Call UnSinkEvents()
End Sub
The resizing of the control is done through the following method. It uses a structure to store the data and use.
Private Sub ResizeParent()
For Each c As Control In ParentForm.Controls
c.Visible = ControlDisplay.ParentMinimized
Next
Visible = True
If Not ControlDisplay.ParentMinimized Then
Me.btnState.Image = My.Resources.RefEdit1
ControlDisplay.ParentClientSize = ParentForm.ClientSize
ControlDisplay.ControlPrevX = Left
ControlDisplay.ControlPrevY = Top
ControlDisplay.ControlAnchor = Anchor
Anchor = AnchorStyles.Left
ParentForm.ClientSize = New Size(Me.Width, Me.Height)
Left = 0
Top = 0
ControlDisplay.ParentPrevBorder = ParentForm.FormBorderStyle
ParentForm.FormBorderStyle = FormBorderStyle.FixedDialog
ControlDisplay.ParentControlBox = ParentForm.ControlBox
ParentForm.ControlBox = False
Else
Me.btnState.Image = My.Resources.RefEdit0
ParentForm.ClientSize = ControlDisplay.ParentClientSize
Anchor = ControlDisplay.ControlAnchor
Left = ControlDisplay.ControlPrevX
Top = ControlDisplay.ControlPrevY
ParentForm.FormBorderStyle = ControlDisplay.ParentPrevBorder
ParentForm.ControlBox = ControlDisplay.ParentControlBox
End If
End Sub
The control can also be resized by using the keyboard shortcut (F4). One benefit that this keyboard shortcut has that the Excel refedit control does not have, is that the (F4) shortcut will resize in both directions. The Excel refedit only shrinks the control. This will Shrink and Grow.
Private Sub txtAddress_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtAddress.KeyDown
If e.KeyCode = Keys.F4 Then
Call DoResize() 'Method that calls the ResizeParent Method
End If
End Sub
To make sure that the Excel.exe process can be killed when the application is closed. I make sure to release any COM objects that the control may be using. I manage this when the control is being disposed.
Private Sub RefEditControl_Disposed(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Me.Disposed
Try
If RefEditExcel IsNot Nothing Then
RemoveHandler xlSheet.SelectionChange, EventDel_SelectionChange
Call NAR(xlSheet)
Call NAR(RefEditExcel)
Call NAR(Connection)
EventDel_SelectionChange = Nothing
ControlDisplay = Nothing
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
You must also make sure that you dispose of the Excel COM objects used outside of the control.
I am sure there a some bugs that need to be addressed, and I will continue to improve this control. If you find anything, please advise on how you fixed it so that I can update the control.
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 10 Feb 2009 Editor: Sean Ewington |
Copyright 2009 by pablleaf Everything else Copyright © CodeProject, 1999-2010 Web17 | Advertise on the Code Project |