.Net


Here I would like to show you a solution for following problem.
One source row coming from Excel contains several values within one column. Each one of these values should be reflected in a separate row in the data destination.
So the basic problem is that there we have a “list column” whose contents should be result in separate rows.

To make the problem more complex: The number of values in the “list column” is variable and there is a second column which contains corresponding values.

Excel Source

Excel Sheet

Excel Sheet

solution: SSIS Script Component

To implement a solution for the problem we use the most adequate item – the Script Component.

  1. We start with a data flow task in our package and add an OLE DB Excel Source component (that returns the source data above).
    We can use following SQL statement:

    SELECT
    F1,F2,F3
    FROM
    [sheet1$B1:D5]

    The imported columns can be named as KEY, PERSON, DEPARTMENT.
    Excel Source

    Excel Source

  2. Then we add a Derived Column Component to the data flow as well.
    Derived Column

    Derived Column

    In order to replace the CRs with commas we replace the imported columns with following formula:

    REPLACE(REPLACE(REPLACE(REPLACE(PERSON,"\n",",")," ",""),",,",","),",,",",")
    REPLACE(REPLACE(REPLACE(REPLACE(DEPARTMENT,"\n",",")," ",""),",,",","),",,",",")

    Derived Column Settings

    Derived Column Settings

  3. As result we receive following list of elements:

    • – -
    • row 1
    • PERSON: Mr. Wayne,Mr. Kent,Mr. Parker
    • DEPARTMENT: Heros/Batman,Heros/Superman,Heros/Spiderman
    • – -
    • row 2
    • PERSON: Mr. Kirk,Ms. Janeway
    • DEPARTMENT: StarTrek/Classic,StartTrek/Voyager
    • – -
    • row 3
    • PERSON: “Mr. Wrong”
    • DEPARTMENT: Wrong entry 1,Wrong entry 2
    • – -
  4. Now we add a Script Component to the data flow.
    When we are prompted to select the type of the component we choose Transformation.

    Script Component

    Script Component

  5. Then we right-click on the Script Component and choose Edit. In the Script Transformation Editor dialog box we select all three columns to make them available as input columns. Now these column are available in the Script code.
    Script Component Columns

    Script Component Columns

  6. Since the tranformation is going to produce more output rows than it receives input rows we have to mark the transformation as asynchronous. This is done by setting the SynchronousInputID property of the output to None.
    Script Component Settings

    Script Component Settings

  7. Next, we have to specify the output columns that the output buffer will contain. So we select the transformation’s output and click Add Column and set the properties (column name and data type).
    Script Component Input / Output rows

    Script Component Input / Output rows

  8. Now we can add the code by clicking on the Design Script button.
    Script Component - Design Script

    Script Component - Design Script

  9. Following Code is splitting our list of items into rows:

    ' Variables
    Dim i As Integer = 0
    Dim itemList_PERSON As String = Row.PERSON
    Dim itemList_DEPARTMENT As String = Row.DEPARTMENT
    Dim delimiter As String = ','
    If Not (String.IsNullOrEmpty(itemList_PERSON) Or String.IsNullOrEmpty(itemList_DEPARTMENT)) Then
    Dim inputListArray_Wer() As String = itemList_PERSON.Split(New String() {delimiter}, StringSplitOptions.RemoveEmptyEntries)
    Dim inputListArray_Abt() As String = itemList_DEPARTMENT.Split(New String() {delimiter}, StringSplitOptions.RemoveEmptyEntries)
    If (inputListArray_Wer.Length = inputListArray_Abt.Length) Then
    ' new rows
    For Each item As String In inputListArray_Wer
    With Output0Buffer
    .AddRow()
    .KEY = CInt(Row.KEY)
    .PERSON = item
    .DEPARTMENT = inputListArray_Abt(i).ToString()
    End With
    ' increase counter
    i = i + 1
    Next
    Else
    ' Filtered Rows
    With Output1Buffer
    .AddRow()
    .KEY = CInt(Row.KEY)
    .PERSON = Row.PERSON
    .DEPARTMENT = Row.DEPARTMENT
    End With
    End If
    End If

    The code shows that there are two outputs. Whenever a record set cannot be split or the columns PERSON and DEPARTMENT have a different number of itemss the rows is redirected to the second output (here Output1).
  10. In order to receive the output from the Script Component we add a Union All Component. Additionally we add two Data Viewer Components, since we want to see the resulting outputs from the Script Component.
    Union ALL

    Union ALL

  11. Running the SSIS package will bring the following result.
    Data Flow completed

    Data Flow completed

  12. As we can see, the first DataViewer Component show us the valid rows produced by our Script Component.
    Data Viewer valid rows

    Data Viewer valid rows

  13. The second DataViewer Component show us the invalid rows produced by our Script Component.
    Data Viewer invalid rows

    Data Viewer invalid rows

download
Of course I provide you the solution as download.

problem
If I have a column with several values (separated by CR) which I need separated into rows then following solution can help:

possible solution: T-SQL
One possible solution using T-SQL is following statement.
The function fn_Split returns all values in a list and the replace function converts the CR (carriage returns) to commas.


SELECT
[Key]
,[b.Value]
,[c.Value]
FROM
[dbo.TableExcel] AS a
CROSS APPLY
fn_Split(REPLACE(a.Persons, CHAR(10)+CHAR(13),','), ',') AS b
CROSS APPLY
fn_Split(REPLACE(a.Departments, CHAR(10)+CHAR(13),','), ',') AS c

The corresponding fn_Split function:

CREATE FUNCTION [dbo].[fn_Split](@text nvarchar(max), @delimiter char(1) = ' ')
RETURNS @Strings TABLE (
position int IDENTITY PRIMARY KEY,
value nvarchar(max)
)
AS
BEGIN
DECLARE @index int
SET @index = -1
WHILE (LEN(@text) > 0)
BEGIN
SET @index = CHARINDEX(@delimiter , @text)
IF (@index = 0) AND (LEN(@text) > 0)
BEGIN
INSERT INTO @Strings VALUES (@text)
BREAK
END
IF (@index > 1)
BEGIN
INSERT INTO @Strings
VALUES (LEFT(@text, @index - 1))
SET @text = RIGHT(@text, (LEN(@text) - @index))
END
ELSE
SET @text = RIGHT(@text, (LEN(@text) - @index))
END
RETURN
END

When Excel data is not coming into SSIS right, then do the following:

  1. use option “IMEX=1” in ConnectionString (Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\..\MyExcel.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1")
  2. modify registry setting “TypeGuessRows=8” to a much higher value
  3. use a sql statement to retrieve data (e.g. “SELECT * FROM [sheet1$A5:M2000]“)

NOTE: The setting IMEX=1 tells the Excel driver to use Import mode. This mode reads the registry setting “ImportMixedTypes=Text” which forces mixed data to be converted to text. To achieve a more reliable column type recognition, the registry setting “TypeGuessRows=8” should be increased. By default the ISAM driver analyzes  the first eight rows and determines the column datatypes from this sampling. If the first analysed rows contain only numeric values, then setting IMEX=1 will not convert this column datatype to Text – it will remain numeric.

ATTENTION: The IMEX setting has some other modes:

  • 0 is Export mode
  • 1 is Import mode
  • 2 is Linked mode (full update capabilities)

Registry Setting Location:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\X.X\Engines\Excel

supplement
If you experience following error the above described solution could fix it.
1. An OLE DB error has occurred. Error code: 0x80040E21.
2. Failed to retrieve long data for column “XYZ”.
3. There was an error with output column “XYZ” (55488) on output “Excel Source Output” (109). The column status returned was: “DBSTATUS_UNAVAILABLE”.
4. The “output column “XYZ” (55488)” failed because error code 0xC0209071 occurred, and the error row disposition on “output column “XYZ” (55488)” specifies failure on error. An error occurred on the specified object of the specified component.
5. [DTS.Pipeline] Error: The PrimeOutput method on component “Info Source” (101) returned error code 0xC0209029. The component returned a failure code when the pipeline engine called PrimeOutput(). The meaning of the failure code is defined by the component, but the error is fatal and the pipeline stopped executing.
6. [DTS.Pipeline] Error: Thread “SourceThread0″ has exited with error code 0xC0047038.

Der Fehler

MSB4019: The imported project “C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\WebApplications\Microsoft.WebApplication.targets” was not found.

konnte bei mir wie folgt behoben werden:

  1. Prüfen, ob sich unter C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets ein File befindet.
  2. Wenn ja, dann dieses an die erwartete Stelle kopieren. Wenn nicht, dann dieses herunterladen (Google).

How to disable caching in SQL Server Reporting Services for Visual Studio in Preview Mode?

SQL Server 2005 Service Pack 1 brings a new feature: caching data in BIDS (Business Intelligence Development Studio) Report Designer. Following objects are cached: all the data query, parameter value and credentials for previewing a report. Sometimes this feature can be annoying, if changes in preview mode should be visible immediately.

In order to disable the caching feature, following key has to be added to the config file ‘RSReportDesigner.config‘.

Key:
<Add Key="CacheDataForPreview" value="False" />

Location:
C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\RSReportDesigner.config
To clear the cache you can also delete the *.data cache file which is located in the report RDL directory.

SSRS: Caching Files (Preview Mode)

SSRS: Caching Files (Preview Mode)

How to pass parameters to ReportViewer Control displaying a remote report (SSRS):

ReportParameter[] parameters = new ReportParameter[2];

protected void Page_Load(object sender, EventArgs e) {
parameters[0] = new ReportParameter("wave_id", "28");
parameters[1] = new ReportParameter("mpc_id", "1530");
ReportViewer1.ServerReport.SetParameters(parameters);
}

VS.PHP

Ein sehr guter PHP Editor inklusive Debugging-, Deployment- und (Smarty)-Template-Unterstützung heißt VS.PHP von Jcx.Software.

Außerdem gibt es 4 verschiedene Versionen:

    1. VS.Php Standalone Edition
      VS.Php for Visual Studio 2005
      VS.Php for Visual Studio .Net 2003
      VS.Php for Visual Studio .Net

Besonders die Integration in Visual Studio ist sehr interessant.

Das sagt Jcx.Software dazu:

If you are a .Net developer you may wonder why VS.Php? Php is one of the most popular languages for developing web applications. In fact, the Php community has the largest pool of rich open source applications, frameworks and resources to make your development life easier. VS.Php lets those who enjoy using Visual Studio use their favorite IDE for Php development. VS.Php also provides many unique features by leveraging the Visual Studio IDE like Php/Javascript debugging.

[Quelle: Jcx.Software]

.Net-Snippets

Unter .Net-Snippets findet man recht gute Lösungen. Sollte man immer mal besuchen, wenn man vor einem Problemchen steht.

Außerdem gibt es noch ein nettes Firefox-Search-Plugin zur schnellen Suche.

.Net-Snippets

EditItemTemplate

Um ein erfolgreiches FindControl in einem EditItemTemplate umzusetzen, sollte folgender Code verwendet werden. In diesem Beispiel wird in einem GridView in einer editierbaren Zeile einer Textbox ein Wert (SelectedValue) aus einer DropDownList zugewiesen, sobald ein Button gedrückt wird.


protected void btnSet_Click(object sender, EventArgs e) {
TextBox txtPredecessorName = (TextBox)((Button)sender).Parent.FindControl("txtPredecessorName");
DropDownList ddKTPredecessors = (DropDownList)((Button)sender).Parent.FindControl("ddKTPredecessors");
txtPredecessorName.Text = ddKTPredecessors.SelectedValue;
}

Nun gibt mittlerweile schon das zweite Service Pack für den SQL Server 2005.

Vor allem die Anbindung von Office 2007 soll zu den Verbesserungen zählen.

Ausserdem wurde ein Feature Pack released, dass die neusten Add-On-Komponenten sowie Datenbankkonnektoren (beispielsweise JDBC) enthält.

Falls ein Fehler beim Importieren von SSIS-Paketen auftritt und der SQL Server nicht unter der Default-Instanz installiert ist, liegt das mit hoher Sicherheit an einem Konfigurationsfehler.

In der Datei steht standardmäßig der Eintrag ., welcher in SERVER\instance geändert werden muss.

Dann findet der Integration Service auch die richtige SQL-Instanz zum speichern von Paketen.

Die Datei befindet sich unter C:\Program Files\Microsoft SQL Server\90\DTS\Binn.

error 1053 integration services

Falls ein Fehlstart der SSIS nach der Installation des Service Pack 1 für den SQL-Server auftritt, dann kann es daran liegen, dass der direkte Internetzugang geblockt wird.

Entweder Firewall konfigurieren oder dem System die aktuellen Proxy-Einstellungen mitteilen.

Den Proxy konfiguriert man dann in der Eingabeaufforderung mit dem Tool proxycfg.exe.

[Quelle: MS Knowledge]

Um ein SSIS-Paket, dass im SSIS-Storage des SQL-Servers (nicht im FileSystem) abgelegt ist aus einer .NET-Anwendung zu starten kann folgender Code verwendet werden:

(more…)

Der lokale ReportViewer und die Verwendung von Parametern

Mit Visual Studio 2005 sowie Web Developer Express Studio wird das ReportViewer-Control mitgeliefert. Dieses Steuerelement kann in .NET-Anwendungen verwendet werden und unterstützt die Darstellung von Berichten, die in Report Definition Language definiert werden. Außerdem kann der ReportViewer Daten filtern, sortieren, gruppieren oder aggregieren. Die Datenpräsentation kann in Listen, Tabellen, Diagrammen und Matrizen erfolgen. Sogar das Conditional Formatting ist möglich. Besonders hilfreich ist die Möglichkeit, Berichte in verschiedene Formate wie PDF oder Excel zu exportieren.

Ein in eine ASP.NET-Anwendung integrierter Bericht könnte so aussehen:
ReportViewer Example

Die Daten für diese Berichte können von jeder Datenquelle kommen. Die Anwendung in der der ReportViewer eingebettet wird ist für die Bereitstellung der Daten zuständig. Daten müssen dem ReportViewer nur in der Form von ADO.NET DataTables oder einer Sammlung von Business Objekten übergeben werden.

(more…)

Merke: Um das Löschen eines Eintrags in einem GridView-Control bestätigen zu lassen, müssen vorher unter Edit Columns alle CommandField-Elemente manuell zum GridView hinzugefügt werden und danach das Delete-Element in ein Template-Field konvertiert werden. Nun ist es möglich diesem Element die Eigenschaft OnClientClick zu übergeben.

Da kommt dann einfach das rein:

OnClientClick="return confirm('Are you sure to delete this element?');"

- Coding4Fun – ..Programmieren zum Spaß.

Bei uns ist der Name Programm: “Coding4Fun – Programmieren zum Spaß“. Klar: Es muss Leute geben, die Lagerverwaltungsprogramme und Steuerberatersoftware programmieren, aber wir bei Coding4Fun werfen den Compiler nur an, wenn das entsprechende Projekt Laune macht. Wichtig dabei: hier ist alles 100% kostenlos! Denn der Spaßfaktor leidet ziemlich, wenn man zahlen muss – das wissen wir aus eigener Erfahrung. Sogar die Visual Studio Express Entwickler-Tools für den anspruchsvollen Code-Heimwerker gibt es als Gratisdownload.

[Quelle: Coding4Fun-Website]

Eine noch ausbaufähige WebSite mit einem guten Konzept. Gehört in die Bookmarks!

In Foren habe ich jetzt oft ueber dieses Problem gelesen, dass bei der Herstellung einer Verbindung zu den MS SQL Server Analysis Services auftritt:

TITLE: Connect to Server
------------------------------
Cannot connect to mycomputername.
------------------------------
ADDITIONAL INFORMATION:
A connection cannot be made. Ensure that the server is running.
(Microsoft.AnalysisServices.AdomdClient)
------------------------------
Unable to write data to the transport connection: An existing connection was
forcibly closed by the remote host. (System)
------------------------------
An existing connection was forcibly closed by the remote host (System)
------------------------------
BUTTONS:
OK
------------------------------

Schnelle Abhilfe schafft hier folgende (unsaubere) Loesung:

  1. SQL Server Configuration Manager starten
  2. im linken Baum auf SQL Server 2005 Services klicken
  3. im rechten Fenster fuer die Analysis Services den Account in einen lokalen Administrator-Account aendern (“this account” oder “dieses Konto”)
  4. danach die Analysis Services neustarten und auf einmal geht’s

Sicherheitstechnisch ist diese Loesung allerdings nicht fuer produktive Systeme zu empfehlen. Bei mir trat dieser Fehler nur bei der Developer Edition des SQL Servers in Verbindung mit Windows XP auf.

Eine saubere Lösung wäre, den Account mit dem der SSAS-Service ausgeführt wird in die Analysis-Gruppe (SQLServer2005MSOLAPUser) aufzunehmen, was man mit der Computerverwaltung (Systemsteurung / Verwaltung) erledigen kann. Bei mir beispielsweise der lokale Dienst. Nicht vergessen sollte man danach, den Dienst neuzustarten.

Quelle:

Ein interessantes und auch hilfreiches Tool ist der .NET Reflector von Lutz Roeder. Mit diesem Tool kann man aus der IL (Intermediate Language, sowas wie Bytecode bei Java) Klassen und Funktionen extrahieren, also Assemblies decompilieren. Das Tool unterstuetzt VB.NET sowie C#.
Uebrigens kann man auf diesem Wege auch aus einer in C# geschriebenen Assembly VisualBasic.NET Code extrahieren und umgekehrt.

Die SQL Server Integration Services erlauben das Zusammenfuehren von Daten aus heterogenen Datenquellen. Um den Ueberblick zu behalten wird der gesamte Datenfluss grafisch dargestellt und modelliert.

Das finde ich klasse, denn gerade wenn man ein Projekt an eine weitere Person uebergeben muss oder selbst an mehreren Projekten arbeitet, behaelt man durch diese kleine Hilfe den Ueberblick besser.

SQL Server Integration Services

An manchen Stellen wird es trotzdem notwendig sein, Programmierfaehigkeiten mitzubringen. Dazu kann dann die Scriptkomponente benutzt werden. Mit folgendem Script kann man auf die Datenquellen in seinem Projekt zugreifen. Aber Achtung es muss eine OLEDB-Verbindung definiert werden!


' initialize connection
Me.myConnection = DirectCast(Dts.Connections("SERVER.Database.root.ADO").AcquireConnection(Dts.Transaction), SqlClient.SqlConnection)
' -- open connection to database --
Try
If Not (myConnection.State.Open = ConnectionState.Open) Then
myConnection.Open()
End If
Catch ex As Exception
MsgBox("Could not open connection to DataBase: " & ex.Message.ToString)
End Try
' -- define data tables --
Dim tblTabelle As New Data.DataTable
' -- define SQL-commands --
Dim cmdSQLTblTabelle As New SqlClient.SqlCommand
cmdSQLTblTabelle.CommandText = "SELECT * FROM tblTabelle;"
cmdSQLTblTabelle.Connection() = myConnection
' -- define DataAdapters --
Dim myDATblTabelle As SqlClient.SqlDataAdapter(cmdSQLTblTabelle)
' -- get data from tables --
myDATblTabelle.FillSchema(tblTabelle, SchemaType.Mapped)
myDATblTabelle.Fill(tblTabelle)
' generate InsertCommand automatically with Commandbuilder
Dim myCommandBuilder As New SqlClient.SqlCommandBuilder(myDATblTabelle)
' show rows of query
msgbox("rows: " & tblTabelle.Rows.Count)