A bit of information:
I would like to populate a stacked column chart with transactions from the last 12 months.
Every column should be a month in the year and the transactions are of course stacked on top of each other.
At the moment, I just have a test document where I pull some data from. I first tried to directly put the data (from the csv) in the chart, but that just resulted in multiple columns with the multiple duplicate x axis label and nothing stacked.
I did some digging and found this solution. unfortunately, the result is not what I'm looking for. The transactions are stacked but the x axis labels are incorrect
At the moment I have
Dim rowsTra() As String = File.ReadAllLines(".\data\transactions.csv")
Dim traVal() As String
Dim preYear As DateTime = DateTime.Now.AddYears(-1)
Dim j As Integer = 0
Dim dtTest As DataTable = New DataTable
dtTest.Columns.Add("col1", GetType(Double))
dtTest.Columns.Add("col2", GetType(String))
dtTest.Columns.Add("col3", GetType(String))
For i As Integer = 0 To rowsTra.Length - 1 Step +1 ' Looping through all transactions
traVal = rowsTra(j).ToString().Split(",")
Dim traDate As String = Convert.ToDateTime(traVal(1))
If (traDate >= preYear) Then ' Check if date is not older than 1 year
Dim conMonth As Date = CDate(traVal(1))
Dim month = conMonth.ToString("MMM yyyy")
dtTest.Rows.Add(traVal(6), month, traVal(4))
Else
i = rowsTra.Length - 1 ' Quit loop if year ends (will only work if csv is chronological
End If
j += 1
Next
Dim dv As DataView = New DataView(dtTest)
dv.Sort = "col2 asc"
chTrend.Series.Clear()
chTrend.Titles.Clear() ' Clear
chTrend.DataBindCrossTable(dv, "col3", "col2", "col1", "Label=col1") ' Populate chart
For Each cs As Series In chTrend.Series ' Stack values
cs.ChartType = SeriesChartType.StackedColumn
Next
By using this csv file I get this result:
Account 1,19 Dec 2021,Man 1,Cat 1,Subcat 1,test,5
Account 2,01 Dec 2021,Man 2,Cat 2,Subcat 2,test,10
Account 5,01 Nov 2021,Man 4,Cat 2,Subcat 2,test,10
Account 4,27 Oct 2021,Man 4,Cat 4,Subcat 4,test,20
Account 3,10 Oct 2021,Man 3,Cat 3,Subcat 3,test,15
Account 1,03 Sep 2020,Man 1,Cat 1,Subcat 1,test,25
= col2 =col3 =col1
Why would it in this case add 4 transactions under the "Dec 2021" when only 2 transactions actually are?
I've noticed that when I change the 3rd listed transaction to another Subcat, all transactions fall under Dec 2021.
Ive also tried to just give col2 in dtTest the Date type but this just gave an even weirder chart and I'm not sure how to then format the date to "MMM yyyy". This is my reason to move from datetime to string
I'm not sure what I'm doing wrong.
Thanks for the input. Sorry for the messy code, still learning.
So I did some experimenting myself and I believe I found "A" solution to my problem.
I'm sharing it, since it might be to helpful to someone in the future.
In the end I came up with this solution.
It not only stacks correctly by adding the extra rows needed (as mentioned in my comment), but also adds up values from already existing categories.
This is something that I was aiming for did not mention in my original question.
I'm definitely not saying this is the best solution and I know it can cause some performance issues with scalability. I'd go so far as to say it might even be just spaghetti code so I'd love to see someone with more experience find a more optimal solution to this problem.
Dim rowsTra() As String = File.ReadAllLines(".\transactions.csv")
Dim traVal() As String
Dim strCat As String = ""
Dim strDate As String = ""
Dim preYear As DateTime = DateTime.Now.AddYears(-1) ' Start date for all visible transactions in chart
Dim dtTrend As DataTable = New DataTable
dtTrend.Columns.Add("outflow", GetType(Double)) ' Columns for DataTable
dtTrend.Columns.Add("date", GetType(String))
dtTrend.Columns.Add("category", GetType(String))
Dim valExist As Boolean
Dim l As Integer = 0 'l
Dim m As Integer = 0 'm
For i As Integer = 0 To rowsTra.Length - 1 Step +1 ' Loop all transactions to add to DataTable and list all dates and categories
traVal = rowsTra(l).ToString().Split(",")
Dim traDate As String = Convert.ToDateTime(traVal(1))
Dim traMonth = CDate(traVal(1)).ToString("MMM yyyy") ' Convert to Month Year
If (traDate >= preYear) Then ' Check if date is not older than 1 year
If dtTrend.Rows.Count = 0 Then ' First transaction loop
dtTrend.Rows.Add(traVal(6), traMonth, traVal(4)) ' Add row to DataTable in order "outflow/date/category"
Else ' If not first transaction
m = 0
valExist = False ' Reset valExist to false
While m < dtTrend.Rows.Count ' Loop DataTable, used to add outflow to existing categories
If dtTrend.Rows(m)(1).ToString = traMonth And dtTrend.Rows(m)(2) = traVal(4) Then ' Check if date and category match between DataTable and Transactions
dtTrend.Rows(m)(0) = dtTrend.Rows(m)(0) + traVal(6) ' Add outflow to existing DataTable row
m = dtTrend.Rows.Count
valExist = True
End If
m += 1
End While
If valExist = False Then ' If combo of date and subcategory does not exist:
dtTrend.Rows.Add(traVal(6), traMonth, traVal(4)) ' Add new line to DataTable
End If
End If
If strCat = "" Then ' If string has no value (first loop). Used to create list of subcategories
strCat = traVal(4)
ElseIf strCat.Contains(traVal(4)) Then ' Check if category already exist in the string
Else
strCat = strCat + "," + traVal(4)
End If
If strDate = "" Then ' Ditto about but for Date
strDate = traMonth
ElseIf strDate.Contains(traMonth) Then
Else
strDate = strDate + "," + traMonth
End If
Else
i = rowsTra.Length - 1 ' Quit loop if year ends (will only work if csv is chronological
End If
l += 1
Next
Dim arrCat() As String = strCat.Split(",") ' Split string to use in array
Dim arrDate() As String = strDate.Split(",")
Dim tfMatch As Boolean
For i As Integer = 0 To arrCat.Length - 1 Step +1 ' Loop existing categories, used to add non existing row
For j As Integer = 0 To arrDate.Length - 1 Step +1 ' Loop existing dates, rows need to be added to get full series
Dim dtRows = dtTrend.Rows.Count
For k As Integer = 0 To dtRows - 1 ' Loop through original DataTable values
If dtTrend.Rows(k)(1) = arrDate(j) And dtTrend.Rows(k)(2) = arrCat(i) Then ' Check if date and categorys match anywhere in the DataTable
tfMatch = True
End If
Next
If tfMatch = True Then ' If match, reset and search with next date
tfMatch = False
Else
dtTrend.Rows.Add(0, arrDate(j), arrCat(i)) ' If no match, add as new row in DataTable
tfMatch = False ' Reset, moving to next category
End If
Next
Next
Dim dv As DataView = New DataView(dtTrend)
dv.Sort = "date desc"
chTrend.Series.Clear() ' Clear chart before fill so no exceptions are generated
chTrend.Titles.Clear()
chTrend.DataManipulator.FilterSetEmptyPoints = True ' Filter to get correct stack
chTrend.DataManipulator.FilterMatchedPoints = True
chTrend.DataBindCrossTable(dv, "category", "date", "outflow", "Label=outflow") ' Populate chart
For Each cs As Series In chTrend.Series ' Removes labels of newly added rows with value "0"
chTrend.DataManipulator.Filter(DataVisualization.Charting.CompareMethod.EqualTo, 0, cs) 'Compare if equal to zero, filter out
cs.ChartType = SeriesChartType.StackedColumn ' Chart type
'Dim dpcp As DataPointCustomProperties = New DataPointCustomProperties
Next
I am trying to populate a gridview with dates.
For example the date today is 2/18/2019 and the next date within 30 days is 3/20/2019. so the desired output shoul'd look like this
No. Date
1 3/20/2019
2 4/19/2019
3 5/19/2019
etc.
but the result is
No. Date
1 3/20/2019
2 3/20/2019
3 3/20/2019
etc.
Here is my code so far.
Dim termCounter As Integer = 36
Dim today As DateTime = DateTime.Today
Dim dueDate As DateTime = today.AddDays(30)
Dim dtable As DataTable = New DataTable()
dtable.Columns.Add("No.")
dtable.Columns.Add("Payment Date")
Dim RowValues As Object() = {"", ""}
Dim dRow As DataRow
Dim tmpDate As Date
For i As Integer = 1 To termCounter
If GridAmortSched.RowCount <= 0 Then
RowValues(0) = i
RowValues(1) = dueDate.ToShortDateString
dRow = dtable.Rows.Add(RowValues)
Else
tmpDate = GridAmortSched.Rows(GridAmortSched.RowCount - 1).Cells(1).Value.ToString()
RowValues(0) = i
RowValues(1) = tmpDate.AddDays(30).ToShortDateString
dRow = dtable.Rows.Add(RowValues)
End If
Next
dtable.AcceptChanges()
GridAmortSched.DataSource = dtable
As is often the case, the code is behaving as you have told it to do, not at you want it to do :-).
Every time you go through the loop, you set tmpDate from the same source and then two lines later, you put the value into RowValues. :
tmpDate = GridAmortSched.Rows(GridAmortSched.RowCount - 1).Cells(1).Value.ToString()
You do not adjust your source by i, nor do you increment it. When you AddDays, you do not adjust the original value either (which would not work because of how and when you assign it).
Two easy fixes (two options)
One. The first is to index the days to be added against the loop value - the simple modification to the code below will achieve this. It is a quick fix and may be harder to maintain in the future - more to the point, is harder to spot if you change something such as the loop starting point.
RowValues(1) = tmpDate.AddDays(30*i).ToShortDateString
Two. The other option is to address the code logic. Set your baseline value and then increment it within the loop.
Dim tmpDate As Date
tmpDate = GridAmortSched.Rows(GridAmortSched.RowCount - 1).Cells(1).Value.ToString() '*** Moved outside of loop
For i As Integer = 1 To termCounter
If GridAmortSched.RowCount <= 0 Then
RowValues(0) = i
RowValues(1) = dueDate.ToShortDateString
dRow = dtable.Rows.Add(RowValues)
Else
RowValues(0) = i
tmpDate = tmpDate.AddDays(30) '*** Increment date every time it passes here
RowValues(1) = tmpDate.ToShortDateString '*** Assign the new value
dRow = dtable.Rows.Add(RowValues)
End If
Next
dtable.AcceptChanges()
GridAmortSched.DataSource = dtable
I created a simple Lending program that generate MONTHLY payment mode. The generated schedule is 4 periods so every month the borrower should pay. Just shown screenshot below.
Here is my code:
Private Sub GenerateScheule()
Dim PrincipalAmount As Double = Me.tbPrincipalAmount.Text
Dim InterestRate As Double = Me.tbInterestRate.Text
Dim Period As Integer = Me.tbPeriod.Text
Dim LoanDate As Date = Me.dtpLoanDate.Text
Dim ModePayment As String = Me.cbModeOfPayment.Text
Me.tbLastPayment.Text = LoanDate.AddMonths(Period)
If cbModeOfPayment.Text = "Semi-Monthly" Then
For i As Integer = 1 To Period
Dim dtDate As Date = LoanDate.AddMonths(i)
dgvLoanSchedule.Rows.Add(i, Format(dtDate, "MMM/dd/yyyy"))
Next
End If
Now i want also to create a SEMI-MONTHLY payment mode. If borrowers has 4 periods it doubles up to 8 periods but in semi-monthly format. Just shown screenshot below.
Please someone help me out. I appreciate your help. Thank you guyz.
This is my code - I want to add combobox for my second column. So that whatever value user enter in that column I can use for further operation. I have changed Items in combo intentionally.
Dim cmbHeaderCell As New ComboBox
cmbHeaderCell1.DropDownStyle = ComboBoxStyle.DropDownList
cmbHeaderCell1.Visible = True
cmbHeaderCell1.Items.Add("India")
cmbHeaderCell1.Items.Add("China")
DGrdVLoadStb.Columns(1).Width = cmbHeaderCell1.Width
cmbHeaderCell1.Location = DGrdVLoadStb.GetCellDisplayRectangle(1, -1,True).Location
cmbHeaderCell1.Size = DGrdVLoadStb.Columns(1).HeaderCell.Size
cmbHeaderCell1.SelectedIndex = 0
Here I am getting the location (0, 0) from GetCellDisplayRectangle(1, -1, True) method. I have checked many related questions on stackOverflow but I didn't get perfect answer please help me. Thank you in advance.
As I wrote in comment, I managed to do this by using,
1. width of first column of datagridview adding 2 to it and
2. making it as X of my combobox loacation and Y as 2.
here is my code,
Dim cmbHeaderCell1 As New ComboBox
cmbHeaderCell1.DropDownStyle = ComboBoxStyle.DropDownList
cmbHeaderCell1.Visible = True
cmbHeaderCell1.Items.Clear()
cmbHeaderCell1.Items.Add("India")
cmbHeaderCell1.Items.Add("China")
DGrdVLoadStb.Columns(1).Width = cmbHeaderCell1.Width
'Dim X As Integer = DGrdVLoadStb.GetCellDisplayRectangle(1, -1, False).Location.X
'Dim Y As Integer = DGrdVLoadStb.GetCellDisplayRectangle(1, -1, True).Location.Y
cmbHeaderCell1.Location = New Point(datagridview1.Columns(0).Width + 2, 2)
cmbHeaderCell1.Size = DGrdVLoadStb.Columns(1).HeaderCell.Size
cmbHeaderCellStressRate.DropDownStyle = ComboBoxStyle.DropDownList
DGrdVLoadStb.Controls.Add(cmbHeaderCell1)
cmbHeaderCell1.SelectedIndex = 0
If any one have better solution please post it I will accept it.
i have created VB.net project.In that i have two textbox,and two buttons
button1-->submit
button2-->Duedate
textbox1 contain the current date
My constraints is if i click button2(Duedate) than add 30 days to textbox1 date and assign that value into textbox2.
How to achieve this?
I want the result like as folloes
If I give textbox1 = 12/12/2009
than
I click Duedate: textbox2.text =11/1/2010
Is it possible.
Thanks in advance.
Like so:
Dim d As Date
If DateTime.TryParse(textbox1.Text, d) Then
textbox2.Text = d.AddDays(30).ToShortDateString()
End If
Your button text should be something like:
If IsDate(TextBox1.Text) Then
Dim newdate As Date = CDate(TextBox1.Text)
newdate = newdate.AddDays(30)
Dim myDateFormat As String = "dd/MM/yyyy" //or whatever
DueDateTExtbox2.Text = newdate.ToString(myDateFormat)
End If
'test data
Dim dStr As String = "25/12/2009"
Dim d, d30 As DateTime
Dim invC As New System.Globalization.CultureInfo("") 'invariant culture
If DateTime.TryParseExact(dStr, "dd/M/yyyy", _
invC, _
Globalization.DateTimeStyles.AllowWhiteSpaces _
Or Globalization.DateTimeStyles.AssumeLocal, d) Then
d30 = d.AddDays(30)
End If