Overblog
Folge diesem Blog Administration + Create my blog
Blog von Olaf Helper

Alternatives Kalender Control für SSRS Report Datums Parameter und das auf dem Report

29. April 2011 , Geschrieben von Olaf Helper Veröffentlicht in #Reporting

Es ist natürlich nicht wirklich als Ersatz für das DatePicker Control für Datumsparameter gedacht, sondern mehr als kleines Gimmick und ist auch eher ein kleines Experiment, was so machbar ist im Microsoft Reporting Services.

Um einen Kalender abbilden zu können, werden natürlich zunächst einmal die Datumswerte für einen Bereich rund um ein vorgegebenes Datum benötigt. Damit man auch eine einfache Liste zu Darstellung verwendet werden kann, sollten die Daten nach Wochentagnamen pivotisiert sein. Das kann mit zwei Funktionalitäten vom Microsoft SQL Server erreicht werden: Eine Common Table Expression zum Erzeugen der Datenreihe und die Pivot Funktion um eine Kalenderwoche / Wochentag Matrix zu erhalten:

Statement: 

  -- Nur für Test in SSMS, für SSRS wieder entfernen
SET LANGUAGE DEUTSCH; -- Wegen fixen Wochentagnamen
DECLARE @startDate date; -- Parameter wie in SSRS definiert
SET @startDate = {d N'2011-01-03'};
;WITH
dates AS
(SELECT CAST(DATEADD(dd, -13 - DATEPART(dw, @startDate)
, @startDate) AS date) as CalendarDate
UNION ALL
SELECT DATEADD(dd, 1, CalendarDate) as CalendarDate
FROM dates
WHERE CalendarDate <
DATEADD(dd, 14 + (7 - DATEPART(dw, @startDate)), @startDate)
)
SELECT IsoWeek, [Montag], [Dienstag], [Mittwoch]
, [Donnerstag], [Freitag], [Samstag], [Sonntag]
FROM
(SELECT DATEPART(iso_week, CalendarDate) AS IsoWeek
,DATENAME(dw, CalendarDate) AS DayName
,CalendarDate
FROM dates
) AS PivotSource
PIVOT (Min(CalendarDate)
FOR DayName IN ( [Montag], [Dienstag], [Mittwoch]
,[Donnerstag], [Freitag], [Samstag], [Sonntag])
) AS PivotTable
ORDER BY [Montag], [Dienstag], [Mittwoch]
, [Donnerstag], [Freitag], [Samstag], [Sonntag]
  Ergebnis: 

 IsoWeek     Montag     Dienstag   Mittwoch   Donnerstag Freitag    Samstag    Sonntag
----------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
51          2010-12-20 2010-12-21 2010-12-22 2010-12-23 2010-12-24 2010-12-25 2010-12-26
52          2010-12-27 2010-12-28 2010-12-29 2010-12-30 2010-12-31 2011-01-01 2011-01-02
1           2011-01-03 2011-01-04 2011-01-05 2011-01-06 2011-01-07 2011-01-08 2011-01-09
2           2011-01-10 2011-01-11 2011-01-12 2011-01-13 2011-01-14 2011-01-15 2011-01-16
3           2011-01-17 2011-01-18 2011-01-19 2011-01-20 2011-01-21 2011-01-22 2011-01-23

 

Da für die PIVOT Funktion fixe Werte für die Wochentage verwendet werden, funktioniert die Abfrage natürlich nur mit deutschen Spracheinstellungen und für die IsoWeek ist natürlich die DATEFIRST Einstellung wichtig; also komplett DE Settings. Als Aggregationsfunktion für PIVOT kann statt MIN auch jede andere Aggregation verwendet werden; es gibt ja nur ein Datum je Woche / Wochentag Gruppierung. Das Aufrechnen des DATEPART(dw,..) Wertes wird hier verwendet, um immer „volle“ Wochen zu erhalten. So enthält das Ergebnis immer die Woche, in der das Datum liegt und jeweils +/- 2 volle Wochen drum rum.

 Weiter geht’s mit dem Report. Da die Daten bereits wie gewünscht aufbereitet sind, reicht eben ein einfaches Listen Control für die Darstellung (abgesehen davon, dass in SSRS 2008/2008R2 eh alles ein Tablix ist). Um die Liste auch als interaktives Control verwenden zu können, wird einfach „Aktion“ Funktion bei den einzelnen Datumsfelder verwendet. Hier gibt man als „Gehe zu Bericht“ den gleichen Bericht wieder an und legt für den Parameter den Wert des aktuellen Feldes an; so wird der Bericht erneut mit dem neuen, angeklickten Datum aufgerufen.

Calender_Action.jpg

Analog kann man über Textboxen / Images Funktionen wie „Heute“, „Vorjahr“ oder „Folgemonat“ umsetzen, nur das hier für den Parameter beim Berichtsaufruf eine Expression verwendet wird, wo auf dem aktuellen Datumsparameter per DateAdd ein Wert aufgerechnet wird bzw. fix auf Today() gesetzt wird.

Das BIDS 2008 Projekt kann von meinem SkyDrive geladen werden, es muss dann nur die Datenquelle angepasst werden, wobei die auch auf die master Datenbank zeigen kann; es wird ja aus keiner Tabelle selektiert, sondern nur eine CTE mit fixen Werten verwendet.

Eine Vorschau des Reports sieht so aus, optisch kann es ja nach Belieben gestaltet werden; die aufs Datum bezogenen Daten können dann unterhalb des Kalenders angezeigt werden:

Calender Preview

 

Weiterlesen

SqlConnection.InfoMessage Ereignis

22. April 2011 , Geschrieben von Olaf Helper Veröffentlicht in #.NET

Wenn man im SSMS = „Microsoft SQL Server Management Studio“ im Query Editor ein T-SQL Statement ausführt, hat man im Standard immer 2 Kartenreiter als Resultat: „Ergebnisse“ und „Meldungen“. Bei einfachen Statements bekommt man unter „Meldungen“ so etwas wie „(5 Zeile(n) betroffen)“ zu sehen. Bei eher administrativen Statements wie DBCC Kommandos werden schon umfangreichere Meldungen ausgegeben und auch die Texte von benutzerdefinierten Meldungen aus PRINT Anweisungen erscheinen dort.
Durchaus informative Meldungen erhält man zum Beispiel bei BACKUP DATABASE Anweisungen; wenn man den Parameter STATS mit angibt, erhält man Fortschrittsmeldungen, wie viel Prozent des Vorganges bereits abgeschlossen sind.

Wenn man solche Kommandos per ADO.NET absetzt, wäre es praktisch, solche Meldungen empfangen zu können, um dem Benutzer ein Feedback zu geben; „Jetzt sind bereits 30% des Backup Vorganges abgeschlossen.“. Nur wie?

Das geht recht einfach über das SqlConnection.InfoMessage Ereignis; hier ein kleines Beispiel als einfache Konsolen Anwendung:

 Imports System.Data.SqlClient 
 Module InfoMessage 
  Sub Main() 
  Console.WriteLine("Start backup") 
  Using conn As New SqlConnection("Data Source=.\SQL105DEV;Initial Catalog=master;Integrated Security=True;") 
   Dim sql = "BACKUP DATABASE [AdventureWorks2008R2] " & _
"TO DISK = N'AdvWorks2K8R2.bak' " & _
"WITH NOFORMAT, INIT, NAME = N'Backup AdventureWorks2008R2' " & _
", SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10;"
  Using cmd As New SqlCommand(sql, conn) 
  AddHandler conn.InfoMessage, New SqlInfoMessageEventHandler(AddressOf OnInfoMessage) 
  conn.Open()
cmd.ExecuteNonQuery()
  End Using 
  End Using 
  Console.WriteLine("Press any key to exit.")
Console.ReadKey()
  End Sub 
  Private Sub OnInfoMessage(sender As Object, args As SqlInfoMessageEventArgs) 
  Console.WriteLine(args.Message) 
  For Each err As SqlError In args.Errors
Console.WriteLine(err.Message)
Next
  End Sub 
 End Module 

 

Ergebnis:

SqlInfoMessage.jpg

 

P.S.: Der im BACKUP Command verwendet Parameter COMPRESS war in den Versionen bis einschließlich MS SQL Server 2008 ausschließlich der Enterprise Edition vorbehalten; seit SQL Server 2008 R2 geht das auch bereits ab der Standard Edition; juhu.

Weiterlesen

Microsoft Virtual Academy

21. April 2011 , Geschrieben von Olaf Helper Veröffentlicht in #MSSQL

Microsoft hat sein Online Fortbildungsprogramm (E-Learning) um die Microsoft Virtual Academy (MVA) erweitert, der man kostenlos bei treten kann.

Momentan werden 4 Kurse angeboten, die sich alle um die Cloud drehen, also um Windows Azure, dabei ist auch ein Kurs zu SQL Azure. Die Kurse beziehen sich inhaltlich mehr auf technologische und administrative Aspekte von Azure, Themen zur Entwicklung sind nicht dabei, das wird nur etwas am Rande behandelt.
Wenn man einen Kurs startet, muss man die Lektionen einen nach dem anderen abarbeiten, wobei die Kursmaterialen aus PDF Dokumenten und WebCasts bestehen. Als Abschluss jedes Kurses kann man eine Prüfung (Self-Assessment) ablegen, dabei werden 5 – 7 Fragen gestellt, die man innerhalb 10 Minuten beantworten muss. Für jede gestartete Lektion und für jede erfolgreich abgeschlossene Prüfung gibt es Punkte, wobei es für die Prüfungen immer die volle Punktezahl gibt, auch wenn ein oder zwei Fragen falsch beantwortet wurden. Von daher sagt die volle erreichte Punktezahl nur aus, das man alles abgearbeitet hat, aber nicht wie gut … mal abgesehen, das man nebenher schummeln könnte und die Antworten im Netz suchen könnte.
Es ist halt nur zur Selbstkontrolle gedacht; eben ein Self-Assessment.

Weiterlesen

Fix für SSMS 2008 R2 IntelliSense nach Installation Visual Studio 2010 SP 1

19. April 2011 , Geschrieben von Olaf Helper Veröffentlicht in #Download MSSQL

Wie ich schon berichtete, gab es nach der Installation des Service Pack 1 für das Microsoft Visual Studio 2010 einige Probleme mit IntelliSense im SQL Server Management Studio (SSMS).

 

Seit kurzen gibt es dazu auch einen MS Support Eintrag:

 

FIX: The IntelliSense feature in SQL Server Management Studio for SQL Server 2008 R2 may stop working after you install Visual Studio 2010 Service Pack 1

und einen Fix dazu; das Problem kann mit dem Cumulative Update package 7 for SQL Server 2008 R2 behoben werden.

Weiterlesen

Verarbeiten von EZB Währungskursen

18. April 2011 , Geschrieben von Olaf Helper Veröffentlicht in #T-SQL

Umrechnungskurse für Währungen werden in vielen Fachbereichen und Anwendungsfällen benötigt. Der Börsenbroker benötigt sie im Sekundentakt für die Aktienbewertung, beim Verkauf von Import-Artikel mit Tagespreisen wird der aktuelle Tageskurs benötigt und die Buchhaltung verwendet für die Fremdwährung OP Bewertung einen Monats-Durchschnittskurs.

Die EZB Europäische Zentralbank veröffentlich die Tages-Umrechnungskurse seit Anfang 1999 als XML Datei im Internet. Man kann eine Datei mit den Kursen des letzten Banktages (TARGET Tag), der letzten 90 Tagen und die gesamte Aufstellung erhalten.

Diese Xml Daten bieten sich natürlich dazu an, sie einzulesen und per T-SQL weiter zu verarbeiten, um so eine Referenztabelle mit Umrechnungskursen zu pflegen. Etwas gekürzt sieht der Inhalt der Xml Datei so aus:

 <?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time='2011-04-18'>
<Cube currency='USD' rate='1.4275'/>
<Cube currency='JPY' rate='118.25'/>
<Cube currency='BGN' rate='1.9558'/>
<Cube currency='CZK' rate='24.188'/>
</Cube>
</Cube>
</gesmes:Envelope>

 

Grundsätzlich ist das Verarbeiten kein Problem, allerdings muss man, um die Xml Daten überhaupt lesen zu können, zunächst die verwendete Namespace mittels WITH XmlNameSpaces deklarieren, hier gesmes:Envelope. Will man zugleich auch noch CTE (Common Table Expressions) verwenden, muss man nur berücksichtigen, das XmlNameSpaces an erste Stelle der WITH Anweisung gesetzt wird, die CTE’s dürfen erst darauf folgen.

Hat man das Namespace erst einmal deklariert, erfolgt das weitere Auslesen der Daten wie bei allen anderen Xml Daten auch. Das ganz Statement für eine Tabelle, das Einlesen und Umwandeln sieht dann so aus:

  -- ECB Währungskurse

 -- Tabelle für die Tageskurse anlegen, sofern noch nicht vorhanden. 
 IF OBJECT_ID('[dbo].[EcbDailyExchangeRates]', 'U ') IS NULL
CREATE TABLE [dbo].[EcbDailyExchangeRates]
( [ExcDate] date NOT NULL
,[Currency] char(3) NOT NULL
,[Rate] decimal(19, 6) NOT NULL
,CONSTRAINT [PK_EcbDailyExchangeRates] PRIMARY KEY CLUSTERED
( [ExcDate] ASC
,[Currency] ASC
) WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF
  ,ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
);
GO
 -- Sourcen der Ecb Xml Dateien:
-- Letzter Tag: http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml
-- Letzten 90 Tage: http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml
-- Komplett: http://www.ecb.int/stats/eurofxref/eurofxref-hist.xml

 -- Laden der Xml Datei in eine Variable 
 DECLARE @ecb XML;
SET @ecb = (SELECT CONVERT(xml, EcbSrc.BulkColumn) AS XmlRates
FROM OPENRowsET( BULK N'D:\eurofxref-hist.xml'
,SINGLE_BLOB) AS EcbSrc);
 -- Selektion der Kurse und Einfügen von fehlenden Werten 
;WITH XMLNAMESPACES
( 'http://www.gesmes.org/xml/2002-08-01' as gesmes
,DEFAULT 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref')

 INSERT INTO [dbo].[EcbDailyExchangeRates]
( [ExcDate], [Currency], [Rate])
SELECT Cubes.Rows.value('@time', 'date') AS [ExcDate]
,Nodes.Rows.value('@Currency', 'char(3)') AS [Currency]
,Nodes.Rows.value('@Rate', 'decimal(19, 6)') AS [Rate]
FROM @ecb.nodes('/gesmes:Envelope/Cube/*') AS Cubes(Rows)
CROSS APPLY
Cubes.Rows.nodes('Cube') as Nodes(Rows)
LEFT JOIN
EcbDailyExchangeRates AS Dst
ON Dst.ExcDate = Cubes.Rows.value('@time', 'date')
AND Dst.Currency = Nodes.Rows.value('@Currency', 'char(3)')
WHERE Dst.ExcDate IS NULL
AND NOT Nodes.Rows.value('@Currency', 'char(3)') IS NULL;
 
Weiterlesen