Třídá pro práci s excelem
Přidáno: 5.3.2010
Kategorie: VB.NET - Komponenty
Autor: Honza Dědek
Při své práci jsem narazil na nutnost vytvořit nějáké specifické sestavy v excelu.
Potřeboval jseml otevřít .xlt šablonu, nalít do ní nějáká data a nechat uživatele aby si výsledný soubor uložil. Požadovaná šablona neměla bohužel databázovou strukturu, takže bylo nutné data ukládat do předem určených buňek manuálně. Navíc jsem potřeboval využívat VBA.
Po vyřešení jsem narazil ještě na jeden problém a to ten, že i po uzavření instance excelu se neukončil její proces a tak dál zabírala paměť (navíc sešit který byl takto otevřený šel znovu otevřít pouze pro čtení).
To se mi taky podařilo vyřešit a výsledek je třída (viz. níže). Je to první verze, takže počítám že v případě potřeby tam přibudou další funkce.
Některé funkce (např. pro čtení a zápis dat) tam jsem jenom pro pohodlnost. K jednotlivým komponentám až na úroveň buněk je možné samozřejmě přistupovat i standartně přes Worksheets.
Kód mi spolehlivě funguje na Office 2003 i Office 2007
Komentář:
- při vytváření objektu je možné si vybrat, zda se zviditelní uživatelské rozhraní, nebo zda si nejdřív doplníte na pozadí data
- sešit je možné průběžně ukládat
- při uzavření si můžete zvolit, zda se má sešit uložit a zda se má zavřít i uživatelské rozhraní excelu (pouze pokud je zobrané, tzn. Visible=True). Pokud nechcete uživatelské rozhraní zavírat, zavoláte metodu CloseExcel s prvním parametrem False. Dojde pouze ke zničení objektů excelu které třída používá a k uvolnění procesu dojde bezprostředně poté, co uživatel zavře excel manuálně. Pokud by jste metodu CloseExcel nezavolali, proces dál poběží i po manuálním uzavření excelu (viz. výše problém s uzavíráním)
Aby to všechno fungovalo, musíte mít nareferencované příslušné knihovny MS Office.
Jsou to:
Microsoft Excel 11.0 Object Library
Microsoft Office 11.0 Object Library
Microsoft Visual Basic for Applications Extensibility 5.3
(Pokud máte nainstalované novější office a tím i novější verze knihoven, mělo by to fungovat taky)
Imports Microsoft.Office.Interop
Imports System.Runtime.InteropServices
Public Class ClassExcel
Implements IDisposable
Private _disposeWithCloseUI As Boolean = True
Private _disposing As Boolean = True
#Region "Properties"
Private _path As String
Public ReadOnly Property Path() As String
Get
Return _path
End Get
End Property
Private _workSheet As Excel.Worksheet
Public Property WorkSheet() As Excel.Worksheet
Get
Return _workSheet
End Get
Set(ByVal value As Excel.Worksheet)
_workSheet = value
End Set
End Property
Private _workbook As Excel.Workbook
Public Property Workbook() As Excel.Workbook
Get
Return _workbook
End Get
Set(ByVal value As Excel.Workbook)
_workbook = value
End Set
End Property
Private _excelApplication As Excel.Application
Public Property ExcelApplication() As Excel.Application
Get
Return _excelApplication
End Get
Set(ByVal value As Excel.Application)
_excelApplication = value
End Set
End Property
Private _sheetName As String
Public Property SheetName() As String
Get
Return _sheetName
End Get
Set(ByVal value As String)
_sheetName = value
Me.WorkSheet = Me.Workbook.Sheets(Me.SheetName)
End Set
End Property
Private _visible As Boolean
Public Property Visible() As Boolean
Get
Return _visible
End Get
Set(ByVal value As Boolean)
_visible = value
Me.ExcelApplication.Visible = value
End Set
End Property
Private _saveBeforeClosing As Boolean = True
Public Property SaveBeforeClosing() As Boolean
Get
Return _saveBeforeClosing
End Get
Set(ByVal value As Boolean)
_saveBeforeClosing = value
End Set
End Property
#End Region
#Region "PrivateMethods"
Sub New(ByVal filePath As String, ByVal sheetName As String, ByVal visible As Boolean)
If IO.File.Exists(filePath) = False Then
MsgBox("Neplatná cesta k souboru", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "Neplatná cesta")
_disposeWithCloseUI = False
_disposing = False
Me.Finalize()
Exit Sub
End If
_excelApplication = New Excel.Application
_path = filePath
_sheetName = sheetName
Me.Workbook = Me.ExcelApplication.Workbooks.Open(Me.Path)
Me.WorkSheet = Me.Workbook.Sheets(Me.SheetName)
Me.Visible = visible
End Sub
Protected Overrides Sub Finalize()
Me.Dispose()
End Sub
#End Region
#Region "PublicMethods"
Public Sub CloseExcel(ByVal CloseUI As Boolean)
If Me.SaveBeforeClosing = True Then SaveChanges()
If CloseUI = True Or Me.Visible = False Then
_disposeWithCloseUI = True
Else
_disposeWithCloseUI = False
End If
Me.Finalize()
End Sub
Public Sub SaveChanges()
Me.Workbook.Save()
End Sub
Public Sub WriteData(ByVal sheetName As String, ByVal Range As String, ByVal Value As Object, Optional ByVal offsetRow As Integer = 0, Optional ByVal offsetColumn As Integer = 0)
Me.SheetName = sheetName
If offsetRow = 0 And offsetColumn = 0 Then
Me.WorkSheet.Range(Range).Value = Value
Else
Me.WorkSheet.Range(Range).Offset(offsetRow, offsetColumn).Value = Value
End If
End Sub
Public Function ReadData(ByVal sheetName As String, ByVal Range As String, Optional ByVal offsetRow As Integer = 0, Optional ByVal offsetColumn As Integer = 0)
Me.SheetName = sheetName
If offsetRow = 0 And offsetColumn = 0 Then
Return (Me.WorkSheet.Range(Range).Value)
Else
Return (Me.WorkSheet.Range(Range).Offset(offsetRow, offsetColumn).Value)
End If
End Function
Public Sub SelectRange(ByVal sheetName As String, ByVal range As String)
Me.SheetName = sheetName
Me.WorkSheet.Range(range).Select()
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
If _disposing = False Then Exit Sub
If _disposeWithCloseUI = True Then
If Me.SaveBeforeClosing = True Then Me.SaveChanges()
Me.ExcelApplication.DisplayAlerts = False
Me.ExcelApplication.Quit()
End If
GC.Collect()
GC.WaitForPendingFinalizers()
Marshal.FinalReleaseComObject(Me.WorkSheet)
Marshal.FinalReleaseComObject(Me.Workbook)
Marshal.FinalReleaseComObject(Me.ExcelApplication)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class