how to check column structure in ssis? - sql

I have a table customer in my sql server.
Columns
Distributer_Code
Cust_code
cust_name
cust_add
zip
tel
dl_number
gstin
we receive customer files from the distributor on a monthly basis.
so sometimes they send files with the wrong structuer.. like maybe gstin is missing or dl_number is missing or gstin is in place of dl_number and dl_number is in place of tel...basically, columns could be split..
when we upload those flat files with SSIS it gives error..and data doesn't get uploaded on the server if the structure is wrong.
I want to upload those data with null data if columns are missing or columns are misplaced.

Solution
Based on your comment, you are handling with flat files. To solve this problem, you have to read all columns as one column and retrieve the structure on the go.
Details
First add a Flat file connection manager.
In the flat file connection manager, go to the Advanced Tab, remove all columns and keep only one column (Column0).
Change the column type to DT_WSTR and the length to 4000.
Add a Dataflow task
Inside the Dataflow task add a Flat File source, a script component and an OLEDB destination.
Open the script component, go to Input/Output Tab and and add 8 output columns (Distributer_Code,Cust_code,cust_name,cust_add,zip,tel,dl_number,gstin)
Change the script language to Visual Basic.
Inside the script write the following code.
Dim Distributer_Code as integer = -1
Dim Cust_code as integer = -1
Dim cust_name as integer = -1
Dim cust_add as integer = -1
Dim zip as integer = -1
Dim tel as integer = -1
Dim dl_number as integer = -1
Dim gstin as integer = -1
Dim intRowIndex as integer = 0
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
If intRowIndex = 0 then
Dim strfields() as string = Row.Column0.split(CChar("|"))
Dim idx as integer = 0
For idx = 0 To strFields.length - 1
Select case str
Case "Distributer_Code"
Distributer_Code = idx
Case "Cust_code"
Cust_code = idx
Case "cust_name"
cust_name = idx
Case "cust_add"
cust_add = idx
Case "zip"
zip = idx
Case "tel"
tel = idx
Case "dl_number"
dl_number = idx
Case "gstin"
gstin = idx
End Select
Next
Else
Dim strfields() as string = Row.Column0.split(CChar("|"))
If Distributer_Code > -1 Then Row.DistributerCode = strfields(Distributer_Code)
If Cust_code > -1 Then Row.Custcode = strfields(Cust_code)
If cust_name > -1 Then Row.custname = strfields(cust_name)
If cust_add > -1 Then Row.custadd = strfields(cust_add)
If zip > -1 Then Row.zip = strfields(zip)
If tel > -1 Then Row.tel = strfields(tel)
If dl_number > -1 Then Row.dlnumber = strfields(dl_number)
If gstin > -1 Then Row.gstin = strfields(gstin)
End If
intRowIndex += 1
End Sub
Map the output columns to the OLEDB Destination

Related

How to retrieve the Custom Text (Assignment) Field value based on a Custom Number value in MS Project VBA?

I can get to the values I am after by hardcoding, for example assignment.Text8 but can't get it to work when I create a variable and try to include it like: "if i = 8 then show me what is in assignment.Texti"
Could be a syntax thing but can't figure it out.
Sub TransferAsgnTextX_to_AsgnTCC_viaNumberedMeans()
Dim t As Task
Dim a As Assignment
Dim nr, i As Integer
i = 1
For Each t In ActiveProject.Tasks
nr = ActiveProject.Tasks(i).Number1
If nr > 0 Then
For Each a In t.Assignments
Select Case a.ResourceName
Case "Productivity"
a.Units = "a.Text" & nr
End Select
Next a
End If
i = i + 1
Next t
End Sub
Above code gives a run-time error 1101, but if I hardcoded say a.Units = a.Text8 then the code runs. But I want to find the custom text field based on the (separate) custom number.
The MS Project API doesn't have a good way to do what you are trying to do for Assignments (it does for Tasks and Resources), so I would recommend creating a function that you can call whenever you want to get the data:
Public Function GetAssignmentTextInfo(a As Assignment, fieldNumber As Integer) As String
If fieldNumber = 1 Then
GetAssignmentTextInfo = a.Text1
End If
If fieldNumber = 2 Then
GetAssignmentTextInfo = a.Text2
End If
If fieldNumber = 3 Then
GetAssignmentTextInfo = a.Text3
End If
If fieldNumber = 4 Then
GetAssignmentTextInfo = a.Text4
End If
'... so on through 30 (for the 30 text fields)
Now you could just call this in your code block:
Sub TransferAsgnTextX_to_AsgnTCC_viaNumberedMeans()
Dim t As Task
Dim a As Assignment
Dim nr, i As Integer
i = 1
For Each t In ActiveProject.Tasks
nr = ActiveProject.Tasks(i).Number1
If nr > 0 Then
For Each a In t.Assignments
Select Case a.ResourceName
Case "Productivity"
'call our function instead of hard coding
a.Units = GetAssignmentTextInfo(a, i) & nr
End Select
Next a
End If
i = i + 1
Next t
End Sub
As an added bonus to enhance the method, you could create an Enum called "FieldType" or something like that and include that as an argument in the GetAssignmentTextInfo function so it could retrieve data from other fields aside from just Text1-30.
Public Enum FieldType
Text = 1
Number = 2
Flag = 3
OutlineCode = 4
'etc...
End Enum
Public Function GetAssignmentInfo(a As Assignment, fieldNumber As Integer, fType As FieldType) As String
If fType = FieldType.Text Then
If fieldNumber = 1 Then
GetAssignmentTextInfo = a.Text1
End If
If fieldNumber = 2 Then
GetAssignmentTextInfo = a.Text2
End If
'... so on through 30 (for the 30 text fields)
End If
If fType = FieldType.Number Then
If fieldNumber = 1 Then
GetAssignmentTextInfo = CStr(a.Number1)
End If
If fieldNumber = 2 Then
GetAssignmentTextInfo = CStr(a.Number2)
End If
'... so on through 20 (for the 20 number fields)
End If
Stephen, if I follow what you are trying to do, you want to change the assignment units for the "Productivity" resource to whatever value is in the Task Number1 field. If so then just do that, i.e.
a.Units = nr
For the Assignment object, there is no way around getting properties other than accessing them directly. So the solution is to use a Select Case statement.
FWIW this would be much simpler if the values were stored at the task level as the Task object offers the GetField method that takes a field ID parameter and returns the variable field value. See I can't access columns in MS Project VSTO Add-In and Can FieldNameToFieldConstant be used with the TaskDependency Object for examples.

The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)

I've a problem when I run simple add-on into SAP Business One. I've gotten this exception through this snippet of this code :
' After changing the item quantity
If (pVal.ItemUID = "mat") And (pVal.ColUID = "ActQuan") And (pVal.EventType = SAPbouiCOM.BoEventTypes.et_VALIDATE) Then
Dim oEditPrice As SAPbouiCOM.EditText ' Item Price
Dim oEditTDTotal As SAPbouiCOM.EditText ' To Date Total
Dim oEditTDQuan As SAPbouiCOM.EditText ' To Date Quan
Dim oEditCuttings As SAPbouiCOM.EditText ' Cuttings
Dim oEditTotal As SAPbouiCOM.EditText ' Total = TDTotal - Cuttings
Dim oEditActQuan As SAPbouiCOM.EditText
' Get the items from the matrix
oEditPrice = colItemPrice.Cells.Item(pVal.Row).Specific
oEditTDTotal = colItemTDTotal.Cells.Item(pVal.Row).Specific
oEditTDQuan = colItemTDQuan.Cells.Item(pVal.Row).Specific
oEditTotal = colItemACuttings.Cells.Item(pVal.Row).Specific
oEditCuttings = colItemCuttings.Cells.Item(pVal.Row).Specific
oEditActQuan = colItemActQuan.Cells.Item(pVal.Row).Specific
' Copy the value of TDQty
Dim tmpInt As Integer
tmpInt = CInt(oEditActQuan.Value)
oEditTDQuan.Value = CInt(tmpInt)
' Copy the value of TDTotal
Dim tmpIn As Integer
tmpIn = CInt(oEditTDQuan.Value) * CInt(oEditPrice.Value)
oEditTDTotal.Value = CInt(tmpIn)
'Calc Total Row - ACuts
Dim tmpTotal As Integer ' temp variable to contain total result
tmpTotal = CInt(oEditTDTotal.Value) - CInt(oEditCuttings.Value)
oEditTotal.Value = CInt(tmpTotal)
' Calc the document total
Dim CalcTotal As Double
Dim i As Integer
CalcTotal = 0
' Iterate all the matrix rows
For i = 1 To oMatrix.RowCount
oEditTotal = colItemACuttings.Cells.Item(i).Specific
CalcTotal += oEditTotal.Value
Next
oDocTotal.Value = CalcTotal
End If
End If
End If
I use VB.Net. I have an issue with ColUID = "ActQuan" . Can anyone help me ?
I changed this column many times and the same error.
Not the exact same thing, but in sap, we get this RPC_E_SERVERFAULT issue when sap scripting settings are not correct. The following changes worked for me:
Open transaction RZ11
Set the following to true:
sapgui/user_scripting
Set the following to false:
sapgui/nwbc_scripting
sapgui/user_scripting_disable_recording
sapgui/user_scripting_force_notification
sapgui/user_scripting_per_user
sapgui/user_scripting_set_readonly
Enable user side scripting.
More detailed documentation can be found here.

Randomly select an item from a list based on a class, repeat number of times based on different numbers

I am not familiar with using macro's, but I think that what I would like excel to perform is best handled with a macro. So I can use all the input you may have!
I have these headers;
ID Tag Pen Sex Weight Class Inside range
With 450 rows of data. Based on the distribution of the weight data, I have in two other columns (class and number) the number of rows I want to select within each class. The selected rows must have the value "Yes" in the column "Inside range".
I want to randomly select the rows, based on the number needed for each class, and copy these rows to a new sheet. It sums up to 30 rows in the new sheet.
I hope you have a suggestion how to complete this action!
can you try the following, you will need to add a reference to Microsoft Scripting Runtime library:
Const rowCount = 450
Public Sub copyRows()
Dim i As Integer
Dim j As Integer
Dim classes As Scripting.Dictionary
Dim source As Worksheet
Dim colNumber As Integer
Dim colClassName as Integer
Dim colInsideRange As Integer
Dim allSelected As Boolean
Dim randomRow as Integer
Dim sumRemaining as Integer
allSelected = False
Set source = Worksheets("YourWorksheetName")
colClassName = 6 'this is the column number where class names are entered. I am assuming 6
colNumber = 7 'this is the column number where number of rows to be selected are entered. I am assuming 7
colInsideRange = 8 'this is the column number where "Inside Range" values are entered. I am assuming 9
For i = 2 to rowCount + 1 'assuming you have a header row
classes(CStr(source.Cells(i, colClassName))) = CInt(source.cells(i, colNumber)
Next i
Do until allSelected
Randomize
randomRow = Int ((Rnd * 450) + 2) 'assuming you have a header row, + 1 if you don't
If classes(CStr(source.Cells(randomRow, colClassName))) = 0 Then
With classes
sumRemaining = 0
For j = 1 to .Count - 1
sumRemaining = sumRemaining + .Items(j)
If sumRemaining > 0 Then Exit For
Next j
allSelected = (sumRemaining = 0)
End With
Else
source.Cells(randomRow, colInsideRange) = "Yes"
classes(CStr(source.Cells(randomRow, colClassName))) = classes(CStr(source.Cells(randomRow, colClassName))) - 1
End If
Loop
'Enter your code to copy rows with "Inside Range" = "Yes"
End Sub
Sorry if there are some errors or typos, I wrote from my mobile phone.

Find Common Values From Datagridview

I Have about 10 (DatagridView Count may varies As per User Selected Files From 2 to 10) Datagridview ,So How can i find common value from all Datagridviews ??
Comment If you need more brief details
Below is mine but It find common from 2 -2 datagridviews
For i As Integer = 1 To dgvCont
For j As Integer = 0 To Main.DGVM(i).Rows.Count - 1
For Each Val As DataGridViewRow In Main.DGVM(i + 1).Rows
If Val.Cells(0).Value = Main.DGVM(i).Rows.Item(j).Cells(0).Value Then
Dim cm As String = Val.Cells(0).Value
If cm = "" Then
Else
Analysis.lvCmn.Items.Add(Val.Cells(0).Value)
End If
End If
Next
Next
Next
I understand that you want to set two nested loops accounting for an undetermined number of elements (items in an array of DataGridView, I presume), performing the checks you want:
For count1 As Integer = 1 To dgvCont 'Assuming indices from 1 to dgvCont
For row1 As Integer = 0 To Main.DGVM(count1).Rows.Count - 1
If (Main.DGVM(count1).Rows(row1).Cells(0).Value Is Nothing) Then Continue For
Dim val1 As String = Main.DGVM(count1).Rows(row1).Cells(0).Value
Dim found As Boolean = False
For count2 As Integer = 1 To dgvCont 'Assuming indices from 1 to dgvCont
If (count2 = count1) Then Continue For
For row2 As Integer = 0 To Main.DGVM(count2).Rows.Count - 1
If (Main.DGVM(count2).Rows(row2).Cells(0).Value Is Nothing) Then Continue For
Dim val2 As String = Main.DGVM(count2).Rows(row2).Cells(0).Value.ToString()
If val1 = val2 Then
Dim cm As String = val1
If cm = "" Then
Else
Analysis.lvCmn.Items.Add(val1)
End If
found = True
Exit For 'By assuming that you want to stop searching after finding a match
End If
Next
If (found) Then Exit For 'By assuming that you want to stop searching after finding a match
Next
Next
Next
Your code is not too clear (neither what you want); but this should give you a good enough start to carry out the implementation you are looking for. Bear in mind that this code (like yours) only considers one column (first one); in case of wanting to iterate through all the columns, you would have to add further nested loops accounting for that.

How to not generate a stack overflow when a sub procedure calls itself?

This code generates a stack overflow. I'm aware it is caused by the procedure calling itself.
What can I do to avoid the stack overflow? Recalling the sub procedure and generating a new random number is the easiest thing to do, however it generates the overflow. The randomly generated number picks a random inventory item, then the if statement matches that number (random inventory item) with the quantity of that item from the deck inventory to make sure it isn't less than 1. If the inventory of that item is 0, the else plays and restarts the procedure, generating a new random number and doing the process all over again. In another procedure I have a function that if the deck's inventory becomes completely empty, then the discard pile replenishes the deck, making the discard pile empty, so there should never be a case where all randomly generated numbers can be associated item with a inventory of 0.
I wonder if I could somehow force the random number generator
Number = (DeckGroup(Rnd.Next(0, DeckGroup.Count)).ID)
not to generate numbers to inventory items DeckGroup(Number).QuantityInteger that are zero. By doing so I wouldn't even need to recall the function.
The random number is generated by a different branch in the same structure group.
Private Sub PlayElse()
Dim CardCheckBoxArray() As CheckBox = {CardCheckBox1, CardCheckBox2, CardCheckBox3, CardCheckBox4, CardCheckBox5}
'Reset Number Generator
Number = (DeckGroup(Rnd.Next(0, DeckGroup.Count)).ID)
Dim PlayerQuantitySubtractionInteger As Integer
For PlayerQuantitySubtractionInteger = ChecksDynamicA To ChecksDynamicB
If CardCheckBoxArray(TextBoxInteger).Checked = True And DeckGroup(Number).QuantityInteger > 0 Then
DeckGroup(Number).QuantityInteger -= 1
'Select the Player depending value of T
Select Case T
Case 0
Player1HandGroup(Number).QuantityInteger += 1
Case 1
Player1HandGroup(Number).QuantityInteger2 += 1
Case 2
Player1HandGroup(Number).QuantityInteger3 += 1
Case 3
Player1HandGroup(Number).QuantityInteger4 += 1
Case 4
Player1HandGroup(Number).QuantityInteger5 += 1
End Select
CardTypeArray(PlayerQuantitySubtractionInteger) = Player1HandGroup(Number).CardType
CardCheckBoxArray(TextBoxInteger).Text = Player1HandGroup(Number).CardNameString
NumberArray(PlayerQuantitySubtractionInteger) = Number
Else
If CardCheckBoxArray(TextBoxInteger).Checked = True And DeckGroup(Number).QuantityInteger < 0 Then
Call PlayElse()
End If
End If
Next PlayerQuantitySubtractionInteger
End Sub
You could use LINQ to weed out all the objects you never want to get first and then use the collection returned by the linq instead of your original collection.
Something like:
Private Sub PlayElse()
Dim CardCheckBoxArray() As CheckBox = {CardCheckBox1, CardCheckBox2, CardCheckBox3, CardCheckBox4, CardCheckBox5}
'Reset Number Generator
Dim temp As IEnumerable(Of LunchMoneyGame.LunchMoneyMainForm.Group) = From r In DeckGroup Where r.QuantityInteger > 0 Select r
If temp IsNot Nothing AndAlso temp.Any Then
Number = (temp(Rnd.Next(0, temp.Count)).ID)
' ** Edit **: This will ensure that you only got 1 object back from the LINQ which can tell you whether or not you have bad data. You *can* exclude this check but its good practice to include it.
Dim obj As LunchMoneyGame.LunchMoneyMainForm.Group = Nothing
Dim t = From r In temp Where r.ID = Number Select r
If t IsNot Nothing AndAlso t.Count = 1 Then
obj = t(0)
End If
If obj IsNot Nothing Then
Dim PlayerQuantitySubtractionInteger As Integer
For PlayerQuantitySubtractionInteger = ChecksDynamicA To ChecksDynamicB
' ** Edit **
obj.QuantityInteger -= 1
'Select the Player depending value of T
Select Case T
Case 0
Player1HandGroup(Number).QuantityInteger += 1
Case 1
Player1HandGroup(Number).QuantityInteger2 += 1
Case 2
Player1HandGroup(Number).QuantityInteger3 += 1
Case 3
Player1HandGroup(Number).QuantityInteger4 += 1
Case 4
Player1HandGroup(Number).QuantityInteger5 += 1
End Select
CardTypeArray(PlayerQuantitySubtractionInteger) = Player1HandGroup(Number).CardType
CardCheckBoxArray(TextBoxInteger).Text = Player1HandGroup(Number).CardNameString
NumberArray(PlayerQuantitySubtractionInteger) = Number
Next PlayerQuantitySubtractionInteger
End If
End If
End Sub
Pass through the list and determine only those that are valid. Then randomly pull from that set. Here is a simple version of it. You could use LINQ as well, but this should be clear enough:
Dim validDeckGroupsIndexes As New List(Of Integer)
For ndx As Integer = 0 to DeckGroup.Count - 1
If DeckGroup(ndx).QuantityInteger > 0 Then
validDeckGroupsIndexes .Add(ndx)
End If
Next ndx
Then use this:
Dim deckGroupNdx As Integer = Rnd.Next(0, validDeckGroupsIndexes.Count)
Number = DeckGroup(deckGroupNdx).ID