I am having an issue summing a column of dollar amounts in a DataTable with VB. I have tried two different ways resulting in two different errors which I am not sure how to resolve. Before I go into the two ways I have tried to solve the problem here is the setup:
I am importing a tab delimited file into a DataTable. The headers are automatically populated with data from the first row in the file.
The DataGridView that displays the Datatable is called DGV_detail.
The column in DGV_detail I am trying to sum occurs at column 3 and is called 'Value-to-date'. This column is full of dollar amount values similar to: $10.00 With the dollar sign and everything.
I am also declaring a view variables and doing some calculations when a button is clicked.
Here is my first approach:
For i As Integer = 0 To DGV_detail.Rows.Count() - 1 Step +1
interestPaidToAccounts = interestPaidToAccounts + DGV_detail.Rows(i).Cells(3).Value
Next
When I try this approach I get the following error:
An unhandled exception of type 'System.InvalidCastException' occurred in Microsoft.VisualBasic.dll
Conversion from string "" to type 'Double' is not valid.
The other methods I was trying to use to solve the problem were (For reference: In these examples I created a variable local to the button_click function that assigned the BGV_detail.DataSource to equal dataTable1):
Dim sumObject = dataTable1.Compute("Sum(Convert(Value-to-date, 'System.Decimal'))", "[Value-to-date] IS NOT NULL")
and
Dim sumObject As Decimal = dataTable1.Compute("Sum(Value-to-date)", "")
Which both produced the following error:
Expecting a single column argument with possible 'Child' qualifier.
I am pretty lost at this point so whatever the community thinks the best method to resolves these problems is, I am open to.
I can provide additional information if needed! :)
Thanks in advance for your help!
The dollar sign is the issue, use mid to remove it and val to convert to number:
val(mid(DGV_detail.Rows(i).Cells(3).Value, 2,DGV_detail.Rows(i).Cells(3).Value.length -1))
Untested, but should get you started ... there are any number of ways to remove the $.
Related
I'm working with Windows Forms Application in Visual Studio 2015, using .NET Framework 4.5.2. So I'm making a simple program which includes a label to display a value. The label (called lblMoney) displays the currency (in this case, $) and then the value (e.g 350). Together it looks like $350.
Now, I made another form with a textbox called txtCash and a button called bApply. You enter any integer (e.g 350) into txtCash. When you press bApply, the number in txtCash will add to the number in lblMoney. So, if you had 5 in lblMoney, and you entered 350 in txtCash, lblMoney would display 355.
Here's my code to add to the number:
My.Forms.VeilSideCash.lblMoney.Text = cstrx + txtCash.Text.ToString
The form VeilSideCash is the form that holds lblMoney.
Here's the code for cstrx:
Dim cstrx = "$" & Val(My.Settings.Money.ToString)
The problem here is that, instead of overwriting to lblMoney, the new number is just added after the original number. So if lblMoney has 5 and you enter 350 into txtCash, lblMoney looks like $5350.
How would I go about overwriting with the new number (adding to) instead of replacing?
Any help would be appreciated. Feel free to edit incase I messed something up while explaining.
The problem with your code is the Option Strict setting for your project. You have it set to Off and this allows your code to freely treat strings as they were numbers and try to use them in mathematical operations.
But, when you use the + operator between two strings, it doesn't matter if, for a human being, the two strings represent a number, the compiler see them as strings (cstrx, txtCash.Text) and thinks that you want to use the concatenation operator defined for strings (the +). Yielding wrong (for you) results .
I really suggest you to not use the automatic conversions made by the compiler on your code, instead, when you need to do math operations, always convert your strings to numbers and do the math with variables of numeric type (You could also change the Option Strict to On, but you should be prepared to solve a lot of problems in your current code)
Instead, with a proper numeric approach, you get the text inside txtCash and try to check if your user has correctly typed a decimal value.
Dim cash As Decimal
if Not decimal.TryParse(txtCash.Text, cash) Then
MessageBox.Show("Invalid cash value")
Return
End if
Now get the text of lblMoney and convert it back to a decimal number alerting the compiler that there is a currency symbol in the text to convert
Dim current As Decimal
current = decimal.Parse(lblMoney.Text, NumberStyles.Currency, CultureInfo.CurrentCulture)
Now you have two numbers and the + operator does what you expect. It adds the two numbers together. Finally you could write back the result with a proper currency formatting
Dim result as Decimal
result = current + cash
lblMoney.Text = result.ToString("C")
You need to remove the "$" and convert to a number. I used a decimal so you can include cents if you want:
Dim sum As Decimal
sum = Val(cstrx.Replace("$","")) + Val(txtCash.Text)
My.Forms.VeilSideCash.lblMoney.Text = sum.ToString()
Dim cstrx = sum.ToString("C")
Note that I used the "C" to format the sum as currency. That automatically puts the $ on for you, or uses other currency symbols for other countries.
I'm not a big VB.net user, so my syntax may be slightly off.
When you use the + operator with string unexpected results can occur. In this case the string with a $ cannot be implicitly converted so you should explicit convert it
Once you convert your strings to a number type you can then use the + operator and they can be implicitly converted back to a string.
My.Forms.VeilSideCash.lblMoney.Text = decimal.Parse(cstrx, NumberStyles.Currency)
+ decimal.Parse(txtCash.Text ,NumberStyles.Currency)
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)
I have an application which is running over hundred of system , I am facing an error in formula statement and only the best and optimal solution to change in Stored Procedure rather change in Report DLL .
Below i m attaching the screen shots , If any body suggest the best solution.
When Gross < 0 then this error occures.
any body suggest the solution
You are getting the error because the string you are converting to number doesn't have any numeric value as string but it contains string characters...
You are again converting Number to String after converting to number... why this multiple conversions.. instead use string value directly..
If you still want to do the same way then suggested approach is to check first with IsNumeric and then convert to number.
Main thing to consider is what does the variable String contains if Gross<0
As part of an access application, i retrieve data from sql server. I have a string field that contains ⅝ in one of the rows, and when i attempt to insert that value into an MsAccess recordset, i get an error
Multiple-step operation generated errors. Check each status value. Here is my code
sFieldValue = getValue() ' when i add a watch, the '⅝' is replaced by a ? e.g. "The result is ⅝" will be shown as "The result is ?"
Rs(sFieldName) = sFieldValue ' error is thrown
I then attempted to hard code the value in VBA
sFieldValue ="⅝"
And the moment i type '⅝' it automatically changes to a question mark
sFieldValue ="?"
I would like to know how i can support characters such as "⅝". The other fractions work just fine, e.g. '½'. I do not want to do any calculations, the fractions are part of a string that comes from a SQL Server, and the problem is, i get a runtime error when i try to add a string value that contains a fraction to a recordset in access.
from this page, it shows that some fractions are supported in utf-8
The problem was that the field type of Rs(sFieldName) was adVarChar. So to fix the problem, i used a adVariant field type in my recordset, and it now accepts the ⅝ vulgar character.
I am creating the recordset on the fly.
Edit: adVarWChar is more appropriate, see comment below
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