Solución:
Antes de responder, no creo que la columna contenga solo LF
porque si el delimitador de fila es CRLF
no lo considerará como delimitador. Entonces probablemente sea CRLF
, pero daré una solución para los dos casos (CRLF o LF)
Solución
Puede solucionar esta situación con los siguientes pasos:
- Primero, en el administrador de conexiones de archivos planos, agregue solo una columna (de tipo
DT_STR
y longitud4000
) por lo que considerará cada fila como una columna. - En la tarea de flujo de datos, debe agregar un componente de secuencia de comandos que corrija la estructura del archivo. y dividir la fila en columnas.
Prueba simple
Consideraré un archivo plano con el siguiente contenido
ID;name;DOB;Notes;ClassID{CRLF}
1;John;2001-01-01;;1{CRLF}
2;Moh;2002-01-01;Very cool{LF}
Genius;2{CRLF}
3;Ali;2000-01-01;Calm;2{CRLF}
- Primero agregaré un administrador de conexión de archivos planos con las siguientes opciones:
- Delimitador de fila = {CRLF}
- Delimitador de fila de encabezado = {CRLF}
-
En la tarea DataFlow agregaré un
Flat File Source
, 2 xScript Component
,OLEDB Destination
-
En el primer componente de script marcaré
Column0
como entrada y agregaré 5 columnas de salidaID,Name,DOB,Notes,ClassID
y estableceré la entrada síncrona de salida comoNone
-
En el primer componente de secuencia de comandos, escribiré una secuencia de comandos que almacene cada línea en una variable de memoria y la asigne a una fila de salida cuando la fila esté completa y haya otra fila presente.
Dim strLine As String = String.Empty Dim strDelimiter As String = ";" Public Sub EmptyMemoryVariables() strLine = String.Empty End Sub Public Sub AssignMemoryVariablesToOutput() With Output0Buffer .AddRow() .NewRow = strLine End With End Sub Public Function AreVariablesEmpty() As Boolean If strLine = "" Then Return True Else Return False End If End Function Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer) Dim strColumns As String() = Row.Column0.Split(CChar(strDelimiter)) If strColumns.Length = 5 Then If Not AreVariablesEmpty() Then AssignMemoryVariablesToOutput() EmptyMemoryVariables() End If strLine = Row.Column0 AssignMemoryVariablesToOutput() EmptyMemoryVariables() Else If strLine.Split(CChar(strDelimiter)).Length = 5 Then AssignMemoryVariablesToOutput() EmptyMemoryVariables() End If strLine &= Row.Column0 End If
-
En el segundo componente de script, dividiré cada fila en columnas
Dim strDelimiter As String = ";"
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim strColumns As String() = Row.NewRow.Split(CChar(strDelimiter))
Row.ID = strColumns(0)
Row.NAME = strColumns(1)
Row.DOB = strColumns(2)
Row.NOTES = strColumns(3)
Row.CLASSID = strColumns(4)
End Sub
Nota importante: el código proporcionado no es óptimo, puede necesitar más validaciones o puede ser más simple y mejor, pero estoy tratando de brindarle la forma en que puede pensar para resolver este problema.
No tengo experiencia en SSIS, pero como desarrollador ETL me he enfrentado a esto muchas veces. Por lo tanto, mis sugerencias pueden no ayudarlo a resolver el problema, pero espero que lo orienten en la dirección correcta.
- Si el campo del problema tiene un calificador de texto (por lo general, comillas simples o dobles) y SSIS admite, úselo
- Además, si hay una opción para obligar a SSIS a usar un delimitador de final de registro diferente a LF (CRLF en este caso), lo usaría (con suerte no hay CRLF en el texto del campo del problema)
- Si el campo del problema no es el último campo, puede contar el número de de-limitadores leyendo el registro completo como un solo campo delimitado por LF para identificar y filtrar los registros del problema (si son pocos) e intentar unirlos espalda
- Si es posible, lea el archivo como un solo registro (si SSIS tiene una opción) y reemplace todos los LF, siempre que CR sea un delimitador de fin de registro consistente de la fuente