Adjust rows in SQL Table - sql

We have a field where users sometimes input incorrect info. It wasn't a problem until now when we tried exporting the info to an external program: the data is causing problems. So the idea is now to fix the rows that have the incorrect data. The problem is that the issue is not in all fields, so I am not sure how to adjust it without accidentally deleting valid info.
I want to remove the space and the "J" and the input after it (it always starts with "J"). I did a query with Left([EU-VAT NR], InStr([EU-VAT NR], "J") - 1), but the problem is that I still want the "SE" and "RO" rows that don't have the incorrect info.
RO 9999999 J11/1/1111
SE999999999
RO9999999
RO99999999 J11/11/1111
RO 99999999
What I've thought of is exporting to Excel and then use text-to-columns to split the info up and delete unwanted info to then paste the corrected info back into the table, but since it is a lot of rows it is impossible to detect if something goes wrong.

Create and use small helper function in your query:
Public Function TrimSpaceJ(ByVal Value As String) As String
TrimSpaceJ = Split(Value, " J")(0)
End Function

Assuming that is the only "J" in string, consider:
Trim(IIf(InStr([EU-VAT NR],"J")>0,Left([EU-VAT NR],InStr([EU-VAT NR],"J")-1),[EU-VAT NR]))
Or
Trim(IIf([EU-VAT NR] LIKE "*J*",Left([EU-VAT NR],InStr([EU-VAT NR],"J")-1),[EU-VAT NR]))

Related

MS Access: Trim a leading character upon input into form field

I'm building an access database, and on my main form, I have a field called "PartNumber." I want to scan data (a part number) into this field using a USB scanner and barcode. However, the barcodes include a leading "P" that isn't actually in the part number, and only serves to identify what kind of object that number is assigned to. I would like to automatically remove that P when I initially scan the data, so that the database stores and displays the correct part number.
I thought about using a query with an expression involving mid() and len(), then setting the control of the form field to that field in the query. However, that won't let me change or input data in the form's table, so it's useless for any records not already in the table.
Any ideas are greatly appreciated. Thanks!
I would do this with VBA, in the AfterUpdate event of the textbox.
Private Sub PartNumber_AfterUpdate()
If Left(Me!PartNumber, 1) = "P" Then
' Remove the first character
Me!PartNumber = Mid(Me!PartNumber, 2)
End If
End Sub
Depending on how the barcode API VBA runs: update tables via SQL or updates current form record in VBA; updates in bulk or updates one at a time. Either way at end of bar code reading when updating field, simply use Replace() in VBA or SQL:
SQL:
UPDATE tablename SET fieldname = Replace(fieldname, 'P', '')
VBA:
Me.fieldname = Replace(Me.fieldname, 'P', '')

Why does addition give type mismatch even when I cast?

I'm performing operations between two blocks of data separated by a blank row, and I need to get the row of the second block. I do this by selecting the top block of data using 'Selection.End(xldown)' and then taking the row from this, and adding two to it. Since there is always a single blank row to separate the blocks, this should work, but on the line where I add two to the row, I get a type mismatch despite the fact that I'm casting the row with CInt before I add. The code in question is
Dim col
col = Split(Selection.Address, "$")(1)
Dim tmp as Integer
tmp = CInt(col) + 2
The last line of this always causes a type mismatch error. Why is that? What's wrong with the cast I'm trying? Most importantly, how do I fix it?
I couldn't find anyone encountering this problem except where they were pulling data from the sheet which seemed like a different set of circumstances.
the way you have it set, you're returning the character representation of the address. Try this:
col = Selection.Column
which should return the numeric position (in my limited testing it does at least)

Column references in formulas

I am a little stuck at the moment. I am working on an array of data and need to find a way to input column numbers into formulas.
-I have used the match function to find the corresponding column number for a value.
ex. "XYZ" matched with Column 3, which is equivalent to C1:Cxxxxxx
-now for inputing the C1:Cxxxxxx into a formula to get data for that particular column, I would like to be able to directly reference the Column 3 part, because I plan on using this workbook in the future and the column needed to run the calculation may or may not be column 3 the next time I use it.
- is there any way to tell excel to use a formula to tell excel which column to use for an equation?
so a little more detail, I have the equation
=AND(Sheet3!$C$1:$C$250000=$A$4,Sheet3!$B$1:$B$250000=$B$4)
instead of specifying to use column C, is there a way to use a formula to tell it to use C?
EDIT: more additional info;
"i am basically running the equivalent of a SQL where statement where foo and bar are true, I want excel to spit out a concatenated list of all baz values where foo and bar are true. ideally i would like it to ONLY return baz values that are true, then I will concat them together separately. the way I got it now, the expression will test every row separately to see if true; if there is 18K rows, there will be 18K separate tests.. it works, but it's not too clean. the goal is to have as much automated as possible. *i do not want to have to go in and change the column references every time I add a new data arra*y"
Thanks
You can use INDEX, e.g. if you have 26 possible columns from A to Z then this formula will give you your column C range (which you can use in another formula)
=INDEX(Sheet3!$A$1:$Z$250000,0,3)
The 0 indicates that you want the whole column, the 3 indicates which column. If you want the 3 can be generated by another formula like a MATCH function
Note: be careful with AND in
=AND(Sheet3!$C$1:$C$250000=$A$4,Sheet3!$B$1:$B$250000=$B$4)
AND only returns a single result not an array, if you want an array you might need to use * like this
=(Sheet3!$C$1:$C$250000=$A$4)*(Sheet3!$B$1:$B$250000=$B$4)
You could use ADDRESS to generate the text, you then need to use INDIRECT as you are passing a string rather than a range to the fomula
=AND(INDIRECT(ADDRESS(1,3,,,"Sheet3") & ":" & ADDRESS(250000,3))=$A$4
,INDIRECT(ADDRESS(1,2,,,"Sheet3") & ":" & ADDRESS(250000,2))=$B$4)
Obviously replace the 3s and 2s in the ADDRESS formulae with your MATCH function you used to get the column number. The above assumes the column for $B$1:$B$25000 is also found using `MATCH', otherwise it is just:
=AND(INDIRECT(ADDRESS(1,3,,,"Sheet3") & ":" & ADDRESS(250000,3))=$A$4
,Sheet3!$B$1:$B$25000=$B$4)
Note a couple of things:
You only need to use "Sheet3" on the first part of the INDRECT
Conditions 3 and 4 in the ADDRESS formula are left as default, this
means they return absolute ($C$1) reference and are A1 style as
opposed to R1C1
EDIT
Given the additional info maybe using an advanced filter would get you near to what you want. Good tutorial here. Set it up according to the tutorial to familiarise yourself with it and then you can use some basic code to set it up automatically when you drop in a new dataset:
Paste in the dataset and then use VBA to get the range the dataset uses then apply the filter with something like:
Range("A6:F480").AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:= _
Sheets("Sheet1").Range("A1:B3"), Unique:=False
You can also copy the results into a new table, though this has to be in the same sheet as the original data. My suggestion would be paste you data into hidden columns to the left and put space for your criteria in rows 1:5 of the visible columns and then have a button that gets the used range for your data, applies the filter and copies the data below the criteria:
Range("A6:F480").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Sheets _
Range("H1:M3"), CopyToRange:=Range("H6"), Unique:=False
Button would need to clear the destination cells first etc, make sure you have enough hidden columns etc but it's all possible. Hope this helps.

VBA texttocolumns ignores one column

I have data that was previously improted into Excel and want to have that data automatically put into the proper format.
Right now my dates look like this: 28122012 which should be 28.12.2012
My code, which I've put together with some sources I've found online, works well except for one snag... it ignores column V:
Dim rngS As Range
For Each rngS In .Range("F:F,U:W").Columns
rngS.TextToColumns Destination:=rngS.Cells(1, 1), _
DataType:=xlFixedWidth, FieldInfo:=Array(0, 4)
Next
I'm not certain why it does this. I've experimented by writing out each column, but no go. Column V remains as it is, while everything around it gets properly formatted.
Any ideas why this could be?
Thanks!
The problem is the field it pastes to is treating the value as numerical.
The only real remedy is to set the type to Text for that and other columns that might have such a date value. Then 01122012 will not lose its starting zero.
Alternatively you could let your follow up code or formula anticipate the missing zeroes and work back to date values using LEFT(), RIGHT() and like functions.

SSIS custom script: loop over columns to concatenate values

I'm trying to create a custom script in SSIS 2008 that will loop over the selected input columns and concatenate them so they can be used to create a SHA1 hash. I'm aware of the available custom components but I'm not able to install them on our system at work.
Whilst the example posed here appears to work fine http://www.sqlservercentral.com/articles/Integration+Services+(SSIS)/69766/ when I've tested this selected only a few and not all columns I get odd results. The script only seems to work if columns selected are in sequential order. Even when they are in order, after so many records or perhaps the next buffer different MD5 hashes are generated despite the rows being exactly the same throughout my test data.
I've tried to adapt the code from the previous link along with these articles but have had no joy thus far.
http://msdn.microsoft.com/en-us/library/ms136020.aspx
http://agilebi.com/jwelch/2007/06/03/xml-transformations-part-2/
As a starting point this works fine to display the column names that I have selected to be used as inputs
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
For Each inputColumn As IDTSInputColumn100 In Me.ComponentMetaData.InputCollection(0).InputColumnCollection
MsgBox(inputColumn.Name)
Next
End Sub
Building on this I try to get the values using the code below:
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim column As IDTSInputColumn100
Dim rowType As Type = Row.GetType()
Dim columnValue As PropertyInfo
Dim testString As String = ""
For Each column In Me.ComponentMetaData.InputCollection(0).InputColumnCollection
columnValue = rowType.GetProperty(column.Name)
testString += columnValue.GetValue(Row, Nothing).ToString()
Next
MsgBox(testString)
End Sub
Unfortunately this does not work and I receive the following error:
I'm sure what I am trying to do is easily achievable though my limited knowledge of VB.net and in particular VB.net in SSIS, I'm struggling. I could define the column names individually as shown here http://timlaqua.com/2012/02/slowly-changing-dimensions-with-md5-hashes-in-ssis/ though I'd like to try out a dynamic method.
Your problem is trying to run ToString() on a NULL value from your database.
Try Convert.ToString(columnValue) instead, it just returns an empty string.
The input columns are not guaranteed to be in the same order each time. So you'll end up getting a different hash any time the metadata in the dataflow changes. I went through the same pain when writing exactly the same script.
Every answer on the net I've found states to build a custom component to be able to do this. No need. I relied on SSIS to generate the indexes to column names when it builds the base classes each time the script component is opened. The caveat is that any time the metadata of the data flow changes, the indexes may change and need to be updated by re-opening and closing the SSIS script component.
You will need to override ProcessInput() to get store a reference to PipelineBuffer, which isn't exposed in ProcessInputRow, where you actually need to use it to access the columns by their index rather than by name.
The list of names and associated indexes are stored in ComponentMetaData.InputCollection[0].InputColumnCollection, which needs to be iterated over and sorted to guarantee same HASH every time.
PS. I posted the answer last year but it vanished, probably because it was in C# rather than VB (kind of irrelevant in SSIS). You can find the code with all ugly details here https://gist.github.com/danieljarolim/e89ff5b41b12383c60c7#file-ssis_sha1-cs