Anleitung: Daten nach Microsoft Excel exportieren
Für Berichte ist es oft notwendig, Daten automatisch nach Microsoft Office Excel zu exportieren. Sie könnten beispielsweise ein Exportskript für Zeitbuchungen erstellen, das automatisch einen Excel-Pivot-Bericht pro Benutzer erzeugt und diesen Bericht per E-Mail versendet.
time cockpit unterstützt zwei Wege, Daten nach Microsoft Office Excel zu exportieren:
- Verwenden Sie die integrierte Exportfunktion von time cockpit.
- Wenn Sie etwas sehr Spezielles benötigen (z. B. eine besondere Formatierung der erzeugten Microsoft-Office-Excel-Datei), können Sie die Microsoft-Office-Automatisierung in IronPython verwenden.
Integrierte Exportfunktion für Microsoft Office Excel verwenden
Das folgende Beispiel zeigt, wie Sie das Ergebnis einer TCQL-Abfrage in einem Skript mithilfe einer Vorlagedatei für den Export exportieren:
Hinweis
Die im folgenden Code gezeigte Methode Export erwartet entweder eine Vorlagedatei oder eine Listendefinition. Wenn Sie eine Vorlage angeben, wird die Listendefinition ignoriert. Wenn Sie keine Vorlagedatei angeben, müssen Sie eine Listendefinition angeben (die Vorlage wird dann automatisch auf Basis der Listendefinition erstellt).
clr.AddReference("TimeCockpit.Data.Export")
from TimeCockpit.Data.Export.Excel import *
from System.Threading import CancellationToken
resultingRows = Context.Select("From T In Timesheet Where T.APP_BeginTime > #2010-01-01# Select T")
sourceList = Context.Model.ModelEntityViews["APP_TimesheetList"].Configuration.Columns
XlsxExporter2.ExportToFile(
"c:\\temp\\Template.xlsx", # Path to template file
"c:\\temp\\export.xlsx", # Target file name
resultingRows, # Rows that should be exported (has to be a list of entity objects)
sourceList, # List definition that acts as the source for the export
None, # Reserved; always pass None here
CancellationToken(False)) # Cancellation token that could be used to cancel the export
Microsoft-Office-Automatisierung in einem Skript verwenden
Das folgende Beispiel zeigt, wie Sie eine Microsoft-Office-Excel-Datei mit Microsoft-Office-Automatisierung erzeugen. Das Skript lädt eine Vorlagearbeitsmappe, erstellt durch Kopieren eines Arbeitsblatts ein Blatt pro Benutzer und füllt das Blatt mit Zeitbuchungen. Feiertage und Wochenenden werden besonders formatiert.
import clr
clr.AddReferenceByName('Microsoft.Office.Interop.Excel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c')
clr.AddReference("System.Core")
from Microsoft.Office.Interop import *
from Microsoft.Office.Interop.Excel import *
from System import *
from System.Linq import Enumerable
# Helper function that sets the background of the entire row
def ColorizeRow(cell):
cell.EntireRow.Interior.ThemeColor = XlThemeColor.xlThemeColorDark1
cell.EntireRow.Interior.TintAndShade = -0.249977111117893
# Helper function that checks if a certain day if no working day
def IsDayOff(day, holidays):
return day.DayOfWeek == DayOfWeek.Saturday or day.DayOfWeek == DayOfWeek.Sunday \
or Enumerable.Count(holidays, lambda h: h.LegalHolidayDate.Day == day.Day) > 0
# Helper function that colorizes the entire day if the day is off
def HandleRowColor(currentDayDate, cell, holidays):
if IsDayOff(currentDayDate, holidays):
ColorizeRow(cell)
# Creates an Excel worksheet for a specific user and month
def AddWorksheet(user, year, month, workbook):
# Get all timesheets for the user
timesheets = Context.SelectWithParams({
"Query": "From T In Timesheet Where T.UserDetail.Username = @Username And :Year(T.BeginTime) = @YearFilter And :Month(T.BeginTime) = @MonthFilter Order By T.BeginTime Select T",
"@Username": user.Username,
"@YearFilter": Decimal(year),
"@MonthFilter": Decimal(month) })
# Get holidays for the corresponding month
holidays = Context.SelectWithParams({
"Query": "From H In LegalHoliday Where :Year(H.LegalHolidayDate) = @YearFilter And :Month(H.LegalHolidayDate) = @MonthFilter Order By H.LegalHolidayDate Select H",
"@YearFilter": Decimal(year),
"@MonthFilter": Decimal(month) })
# Add sheet for user
workbook.Worksheets["Tabelle1"].Copy(Before = workbook.Worksheets[1])
ws = workbook.Worksheets[1]
ws.Name = user.Lastname + ", " + user.Firstname
ws.Activate()
rowIndex = 2
totalWorkingHours = 0
hoursPerDay = user.WeeklyHoursOfWork / 5
prevDay = 0
# Loop over all days of the month
for currentDay in range(1, DateTime(year, month, 1).AddMonths(1).AddDays(-1).Day + 1):
currentDayDate = DateTime(year, month, currentDay)
dailyTimesheets = Enumerable.Where(timesheets, lambda t: t.BeginTime.Day == currentDay)
if Enumerable.Count(dailyTimesheets) > 0:
# There are timesheets for this day
for timesheet in dailyTimesheets:
# Add row for timesheet
HandleRowColor(currentDayDate, ws.Cells[rowIndex, 1], holidays)
if prevDay != timesheet.BeginTime.Day:
# Don't repeat day index for mulitple rows of the same day
ws.Cells[rowIndex, 1].Value2 = timesheet.BeginTime.Day
ws.Cells[rowIndex, 2].Value2 = timesheet.BeginTime
ws.Cells[rowIndex, 3].Value2 = timesheet.EndTime
ws.Cells[rowIndex, 4].Value2 = timesheet.DurationInHours / 24
ws.Cells[rowIndex, 5].Value2 = timesheet.Description
totalWorkingHours = totalWorkingHours + timesheet.DurationInHours
prevDay = timesheet.BeginTime.Day
rowIndex = rowIndex + 1
else:
# There are no timesheets for this day
HandleRowColor(currentDayDate, ws.Cells[rowIndex, 1], holidays)
ws.Cells[rowIndex, 1].Value2 = currentDay
rowIndex = rowIndex + 1
# Add sums
ws.Cells[rowIndex,2].Value2 = 'Gesamt:'
ws.Cells[rowIndex,4].Value2 = (totalWorkingHours)/ 24
rowIndex = rowIndex + 1
# Open Excel (visible just for demo purposes)
ex = Excel.ApplicationClass()
ex.Visible = True
ex.DisplayAlerts = False
workbook = ex.Workbooks.Open(r"c:\temp\MonthlyReport.xlsx")
users = Context.Select("From U In UserDetail Order By U.Username Select U")
for user in users:
AddWorksheet( user, 2017, 5, workbook )
print "Done!"
Excel-Export mit einer Aktion in die Benutzeroberfläche integrieren
Sie können ein Exportskript in eine Aktion umwandeln, um in der Benutzeroberfläche von time cockpit eine Schaltfläche anzubieten, die die Daten der ausgewählten Zeile einer Liste exportiert. Das folgende Beispiel zeigt, wie das oben gezeigte Beispiel als Aktion zur Entität APP_UserDetail hinzugefügt werden kann:
Hinweis
Beachten Sie, dass der Code der Aktion nur eine einzige def-Anweisung auf oberster Ebene enthalten darf! Wenn Sie Hilfsfunktionen benötigen, müssen Sie diese als verschachtelte Funktionen innerhalb der einen Funktion auf oberster Ebene definieren (siehe Beispielcode unten).
import clr
clr.AddReferenceByName('Microsoft.Office.Interop.Excel, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c')
clr.AddReference("System.Core")
from Microsoft.Office.Interop import *
from Microsoft.Office.Interop.Excel import *
from System import *
from System.Linq import Enumerable
def ExportTimesheetProtocolToExcel(actionContext):
# Helper function that sets the background of the entire row
def ColorizeRow(cell):
cell.EntireRow.Interior.ThemeColor = XlThemeColor.xlThemeColorDark1
cell.EntireRow.Interior.TintAndShade = -0.249977111117893
# Helper function that checks if a certain day if no working day
def IsDayOff(day, holidays):
return day.DayOfWeek == DayOfWeek.Saturday or day.DayOfWeek == DayOfWeek.Sunday \
or Enumerable.Count(holidays, lambda h: h.LegalHolidayDate.Day == day.Day) > 0
# Helper function that colorizes the entire day if the day is off
def HandleRowColor(currentDayDate, cell, holidays):
if IsDayOff(currentDayDate, holidays):
ColorizeRow(cell)
# Creates an Excel worksheet for a specific user and month
def AddWorksheet(user, year, month, workbook):
# Get all timesheets for the user
timesheets = Context.SelectWithParams({
"Query": "From T In Timesheet Where T.UserDetail.Username = @Username And :Year(T.BeginTime) = @YearFilter And :Month(T.BeginTime) = @MonthFilter Order By T.BeginTime Select T",
"@Username": user.Username,
"@YearFilter": Decimal(year),
"@MonthFilter": Decimal(month) })
# Get holidays for the corresponding month
holidays = Context.SelectWithParams({
"Query": "From H In LegalHoliday Where :Year(H.LegalHolidayDate) = @YearFilter And :Month(H.LegalHolidayDate) = @MonthFilter Order By H.LegalHolidayDate Select H",
"@YearFilter": Decimal(year),
"@MonthFilter": Decimal(month) })
# Add sheet for user
workbook.Worksheets["Tabelle1"].Copy(Before = workbook.Worksheets[1])
ws = workbook.Worksheets[1]
ws.Name = user.Lastname + ", " + user.Firstname
ws.Activate()
rowIndex = 2
totalWorkingHours = 0
hoursPerDay = user.WeeklyHoursOfWork / 5
prevDay = 0
# Loop over all days of the month
for currentDay in range(1, DateTime(year, month, 1).AddMonths(1).AddDays(-1).Day + 1):
currentDayDate = DateTime(year, month, currentDay)
dailyTimesheets = Enumerable.Where(timesheets, lambda t: t.BeginTime.Day == currentDay)
if Enumerable.Count(dailyTimesheets) > 0:
# There are timesheets for this day
for timesheet in dailyTimesheets:
# Add row for timesheet
HandleRowColor(currentDayDate, ws.Cells[rowIndex, 1], holidays)
if prevDay != timesheet.BeginTime.Day:
# Don't repeat day index for mulitple rows of the same day
ws.Cells[rowIndex, 1].Value2 = timesheet.BeginTime.Day
ws.Cells[rowIndex, 2].Value2 = timesheet.BeginTime
ws.Cells[rowIndex, 3].Value2 = timesheet.EndTime
ws.Cells[rowIndex, 4].Value2 = timesheet.DurationInHours / 24
ws.Cells[rowIndex, 5].Value2 = timesheet.Description
totalWorkingHours = totalWorkingHours + timesheet.DurationInHours
prevDay = timesheet.BeginTime.Day
rowIndex = rowIndex + 1
else:
# There are no timesheets for this day
HandleRowColor(currentDayDate, ws.Cells[rowIndex, 1], holidays)
ws.Cells[rowIndex, 1].Value2 = currentDay
rowIndex = rowIndex + 1
# Add sums
ws.Cells[rowIndex,2].Value2 = 'Gesamt:'
ws.Cells[rowIndex,4].Value2 = (totalWorkingHours)/ 24
rowIndex = rowIndex + 1
# make sure that input set contains at least one object
if (Enumerable.Count[EntityObject](actionContext.InputSet) > 0):
# Open Excel (visible just for demo purposes)
ex = Excel.ApplicationClass()
ex.Visible = True
ex.DisplayAlerts = False
workbook = ex.Workbooks.Open(r"C:\temp\MonthlyReport.xlsx")
for user in actionContext.InputSet:
AddWorksheet( user, 2017, 5, workbook )