I am creating an Excel pie and bar charts from exported data pragmatically. Here I need to pick the cell range dynamically. For example, after header name all data should be picked up until cell contains "TOTAL" line.
Below is my current code.
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("oversight")) Then 'This is Summary Level
Dim worksheet2 As ExcelWorksheet = pkg.Workbook.Worksheets.Add("Chart - CY Consumable")
worksheet2.DefaultColWidth = 15
Dim consumableChart As OfficeOpenXml.Drawing.Chart.ExcelPieChart = worksheet2.Drawings.AddChart("ConsumableChart", OfficeOpenXml.Drawing.Chart.eChartType.Pie)
Dim r1, r2 As ExcelRange
r1 = worksheet.Cells("A6:A12") // here I want it to be selected dynamically after header and before the total line
r2 = worksheet.Cells("B6:B12")
consumableChart.Series.Add(r2, r1)
consumableChart.Style = OfficeOpenXml.Drawing.Chart.eChartStyle.Style2
consumableChart.Title.Text = "FY 2018 Consumable by Regional & Central Oversight Programs"
consumableChart.Legend.Remove()
consumableChart.SetPosition(1, 1, 1, 1)
consumableChart.SetSize(1040, 880)
consumableChart.DataLabel.ShowLeaderLines = True
consumableChart.DataLabel.ShowCategory = True
consumableChart.DataLabel.ShowPercent = True
Thanks in advance.
Dim totalRow As Integer
If ds.Tables.Count > 0 Then
Dim k As Integer = 0
For j As Integer = 0 To ds.Tables(0).Columns.Count - 1
If Not skip.Contains(j) Then
If columnNames.Count > 0 AndAlso columnNames.Count = (ds.Tables(0).Columns.Count - skip.Count) Then
strTitle = columnNames(k)
Else
strTitle = ds.Tables(0).Columns(j).ColumnName.Replace("_", " ")
End If
worksheet.Cells(p, k + 1).Value = strTitle
k = k + 1
End If
Next
Dim i As Integer = p + 1
For Each r As DataRow In ds.Tables(0).Rows
If includeTotals OrElse (Not r.Item(2).ToString().Trim().ToUpper().StartsWith("TOTAL") AndAlso _
Not r.Item(2).ToString().Trim().ToUpper().StartsWith("SUBTOTAL") AndAlso _
Not r.Item(2).ToString().Trim().ToUpper().StartsWith("TOTAL") AndAlso _
Not r.Item(2).ToString().Trim().ToUpper().StartsWith("SUBTOTAL")) Then
k = 0
For j As Integer = 0 To ds.Tables(0).Columns.Count - 1
If Not skip.Contains(j) Then
If r.Item(j) Is DBNull.Value Then
worksheet.Cells(i, k + 1).Value = ""
Else
If k = 0 Then
worksheet.Cells(i, k + 1).Style.Numberformat.Format = "#"
worksheet.Cells(i, k + 1).Value = r.Item(j).ToString()
Else
worksheet.Cells(i, k + 1).Value = r.Item(j)
End If
End If
// Checking if it is first col last row
If r.Item(j).ToString().Contains("TOTAL") Then
totalRow = i
End If
If r.Item(j).GetType().Name = "Decimal" Then
If roundUp Then
If useParens Then
worksheet.Cells(i, k + 1).StyleID = 2
Else
worksheet.Cells(i, k + 1).StyleID = 2 '4
End If
Else
If useParens Then
worksheet.Cells(i, k + 1).StyleID = 1
Else
worksheet.Cells(i, k + 1).StyleID = 1 '3
End If
End If
End If
k = k + 1
End If
Next
i = i + 1
End If
Next
End If
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("oversight")) Then 'This is Summary Level
Dim worksheet2 As ExcelWorksheet = pkg.Workbook.Worksheets.Add("Chart - CY Consumable")
worksheet2.DefaultColWidth = 15
// showing the criteria
p = 1
If includeCriteria Then
Try
Dim reportTitle As String = String.Empty
reportTitle = "Central/Regional Oversight Programs"
Dim sb As StringBuilder = New StringBuilder()
sb.Append(reportTitle)
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
sb.Append("Budget Fiscal Year : ")
sb.Append(HttpContext.Current.Session("bfy"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
sb.Append("Currently viewing transactions from inception through ")
Dim fm As Integer = CInt(HttpContext.Current.Session("fm"))
If fm < 4 Then
sb.Append(MonthName(fm + 9))
sb.Append(" ")
sb.Append(CInt(HttpContext.Current.Session("fy")) - 1)
Else
sb.Append(MonthName(fm - 3))
sb.Append(" ")
sb.Append(HttpContext.Current.Session("fy"))
End If
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("division")) Then
sb.Append("Fund Center(s) : ALL")
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
Else
sb.Append("Fund Center(s) : ")
sb.Append(HttpContext.Current.Request.QueryString("division"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
End If
If String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("fa5")) Then
sb.Append("Func Area 5 : ALL")
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
Else
sb.Append("Func Area 5 : ")
sb.Append(HttpContext.Current.Request.QueryString("fa5"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
End If
If Not String.IsNullOrEmpty(HttpContext.Current.Request.QueryString("oversight")) Then
sb.Append("Oversight Program - ")
sb.Append(HttpContext.Current.Request.QueryString("oversight"))
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
End If
sb.Append("FBMS data as of ")
sb.Append(HttpContext.Current.Application("lastUpdated_BIA"))
sb.Append(" at close of business.")
worksheet2.Cells(p, 1).Value = sb.ToString()
sb.Length = 0
p = p + 1
worksheet2.Cells(p, 1).Value = ""
p = p + 1
Catch ex As Exception
For r As Integer = 1 To p - 1
worksheet2.DeleteRow(1, True)
Next
p = 1
End Try
End If
//create chart in new tab
Dim consumableChart As OfficeOpenXml.Drawing.Chart.ExcelPieChart = worksheet2.Drawings.AddChart("ConsumableChart", OfficeOpenXml.Drawing.Chart.eChartType.Pie)
Dim r1, r2 As ExcelRange
// setting the value to check the last row
Dim startColumn As String = "A"
Dim endColumn As String = "B"
Dim startIndex As Integer = 8 // Index where to start
Dim endIndex As Integer = totalRow - 1 'this is determined based on the TOTAL Line from above code
// checking and setting the values and label of pie chart
r1 = worksheet.Cells(String.Concat(startColumn, startIndex.ToString(), ":", startColumn, endIndex))
r2 = worksheet.Cells(String.Concat(endColumn, startIndex.ToString(), ":", endColumn, endIndex))
consumableChart.Series.Add(r2, r1)
consumableChart.Style = OfficeOpenXml.Drawing.Chart.eChartStyle.Style2
consumableChart.Title.Text = "FY 2018 Consumable by Regional & Central Oversight Programs"
consumableChart.Legend.Remove()
consumableChart.SetPosition(5, 5, 5, 5)
consumableChart.SetSize(1040, 880)
consumableChart.DataLabel.ShowLeaderLines = True
consumableChart.DataLabel.ShowCategory = True
consumableChart.DataLabel.ShowPercent = True
Related
The code is not working in this way, but if i use ('Wks_So.Range("A9:A150").ClearContents), instead of (Wks_So.Range("A9", Range("A9").End(xlDown)).ClearContents), the code has no problem at all.
My aim for the selection is to clear all the contents from A9 to the last cell of column A with values
Dim i As Integer
Dim j As Integer
Dim x As Integer
Application.Calculation = xlCalculationManual
Set Wks_Sb = Worksheets("Scarico_Bond")
Set Wks_So = Worksheets("Scarico_Other")
Set Wks_I = Worksheets("Invio")
Wks_Sb.Range("A9", Range("A9").End(xlDown)).ClearContents
'Wks_Sb.Range("A9:A150").ClearContents
Wks_So.Range("A9", Range("A9").End(xlDown)).ClearContents
here is the error
'Wks_So.Range("A9:A50").ClearContents
Wks_Sb.Range("D9:D140").Interior.Color = vbWhite
j = 9
k = 9
x = 8
For i = 7 To 150
If InStr(1, (Wks_I.Cells(i, 4).Value), "Obbligazioni") > 0 Then
Wks_Sb.Cells(j, 1) = x - 7
j = j + 1
Else
If InStr(1, (Wks_I.Cells(i, 4).Value), "Fondi/ETF") > 0 Then
Wks_So.Cells(k, 1) = x - 7
k = k + 1
End If
End If
x = x + 1
Next i
Application.Calculation = xlCalculationAutomatic
End Sub
I would do like this and also define some variables:
Sub yourSub()
Dim i, j, k, x As Integer
Dim lastRow_Sb, lastRow_So, lastRow_I as Integer
Dim wb As Workbook
Dim Wks_Sb, Wks_So, Wks_I As Worksheet
Set wb = ActiveWorkbook
Set Wks_Sb = wb.Worksheets("Scarico_Bond")
Set Wks_So = wb.Worksheets("Scarico_Other")
Set Wks_I = wb.Worksheets("Invio")
lastRow_Sb = Wks_Sb.Cells.SpecialCells(xlLastCell).Row
lastRow_So = Wks_So.Cells.SpecialCells(xlLastCell).Row
lastRow_I = Wks_I.Cells.SpecialCells(xlLastCell).Row
Application.ScreenUpdating = False
Wks_Sb.Range("A9:A" & lastRow_Sb).ClearContents
Wks_So.Range("A9:A" & lastRow_So).ClearContents
Wks_Sb.Range("D9:D140").Interior.Color = vbWhite
j = 9
k = 9
x = 8
For i = 7 To lastRow_I 'Or should this always be 150?
If InStr(1, (Wks_I.Cells(i, 4).Value), "Obbligazioni") > 0 Then
Wks_Sb.Cells(j, 1) = x - 7
j = j + 1
Else
If InStr(1, (Wks_I.Cells(i, 4).Value), "Fondi/ETF") > 0 Then
Wks_So.Cells(k, 1) = x - 7
k = k + 1
End If
End If
x = x + 1
Next i
Application.ScreenUpdating = True
End Sub
You should use End(xlUp) instead of twice End(xlDown):
Change
Wks_Sb.Range("A9", Range("A9").End(xlDown)).ClearContents
'Wks_Sb.Range("A9:A150").ClearContents
Wks_So.Range("A9", Range("A9").End(xlDown)).ClearContents
to:
Wks_Sb.Range("A9", Wks_Sb.Range("A1000000").End(xlUp)).ClearContents
The code is working for 3 times in Excel VBA but at the forth time it gives an error. When I put a toggle point there, the code cannot pass "Duration = Duration + drtn" and "Type MisMatch" error shows up. Is there any way to fix the code?
Function simul(t)
Dim wk As Worksheet
Set wk = Worksheets("Simulation")
Dim FoundCell As Range
Duration = 0
i = 1
char = "StartStep"
drtn = 0
While i = 1
m = WorksheetFunction.CountIf(Range("A2:A30"), char)
Set FoundCell = wk.Range("A:A").Find(char)
x = FoundCell.Row
y = FoundCell.Row
Dim myarray() As Variant
ReDim myarray(m)
For j = 0 To m - 1
myarray(j) = wk.Range("E" & x)
x = x + 1
Next
If char = "A" Then
drtn = Application.Evaluate("LOGNORM.INV(RAND(),r5,r6)")
ElseIf char = "B" Then
drtn = Application.Evaluate("ABS(NtLogisticInv(RAND(),r29,r30)")
ElseIf char = "C" Then
drtn = Application.Evaluate("r17*(-LN(1-RAND()))^(1/r18)")
Else
i = 0
drtn = 0
End If
Duration = Duration + drtn
r = Rnd()
k = 0
While r > myarray(k)
k = k + 1
Wend
char = wk.Range("B" & y + k)
Wend
wk.Range("U" & t) = Duration
End Function
I have a worksheet with over 60,000 rows and two columns. One column is transaction id, the other is item. I want to find the combinations of items in the orders. I found this vba code from someone with a similar problem
Sub basket()
On Error Resume Next
Dim ps(2, 20)
r = 3
tr = Cells(2, 1)
Item = Cells(2, 2) + "."
ps(1, 1) = 1
ps(2, 1) = Len(Item)
r2 = 2
r3 = 3
ic = 2
While Cells(r, 1) <> ""
If Cells(r, 1) <> tr Then
o = 1
k = 1
If ic > 1 Then
ic = ic - 1
While o = 1
For i = 1 To ic
entry = Mid(Item, ps(1, i), ps(2, i))
For j = i + k To ic
entry = entry & Mid(Item, ps(1, j), ps(2, j))
Cells(r2, 10) = tr
Cells(r2, 11) = entry
r2 = r2 + 1
x = 0
x = Application.WorksheetFunction.Match(entry, Range("e:e"), 0)
If x = 0 Then
x = r3
Cells(x, 5) = entry
r3 = r3 + 1
End If
Cells(x, 6) = Cells(x, 6) + 1
Next j
Next i
If k > Len(Item) - 1 Then o = 0
k = k + 1
Wend
End If
Item = ""
ic = 1
tr = Cells(r, 1)
End If
ps(1, ic) = Len(Item) + 1
ps(2, ic) = Len(Cells(r, 2)) + 1
Item = Item + Cells(r, 2) + "."
r = r + 1
ic = ic + 1
Wend
o = 1
k = 1
If ic > 1 Then
ic = ic - 1
While o = 1
For i = 1 To ic
entry = Mid(Item, ps(1, i), ps(2, i))
For j = i + k To ic
entry = entry & Mid(Item, ps(1, j), ps(2, j))
Cells(r2, 10) = tr
Cells(r2, 11) = entry
r2 = r2 + 1
x = 0
x = Application.WorksheetFunction.Match(entry, Range("e:e"), 0)
If x = 0 Then
x = r3
Cells(x, 5) = entry
r3 = r3 + 1
End If
Cells(x, 6) = Cells(x, 6) + 1
Next j
Next i
If k > Len(Item) - 1 Then o = 0
k = k + 1
Wend
End If
End Sub
Which worked when I ran the exact same code but with item categories. The problem is I'm running it with the item names and it's always crashing my Excel. Is there anyone that can guide me in the right direction?
this is the worksheet that doesn't work
this is what I get when I run it with the item category which works. They're the exact same data, one just has it as item category, and the other is item name.
Your code sample didn't do anything for me. It ran, but it didn't actually produce any kind of results at all. I did a quick Google search and found this.
Sub ListCombinations()
Dim col As New Collection
Dim c As Range, sht As Worksheet, res
Dim i As Long, arr, numCols As Long
Set sht = ActiveSheet
'lists begin in A1, B1, C1, D1
For Each c In sht.Range("A2:B2").Cells
col.Add Application.Transpose(sht.Range(c, c.End(xlDown)))
numCols = numCols + 1
Next c
res = Combine(col, "~~")
For i = 0 To UBound(res)
arr = Split(res(i), "~~")
sht.Range("H1").Offset(i, 0).Resize(1, numCols) = arr
Next i
End Sub
'create combinations from a collection of string arrays
Function Combine(col As Collection, SEP As String) As String()
Dim rv() As String
Dim pos() As Long, lengths() As Long, lbs() As Long, ubs() As Long
Dim t As Long, i As Long, n As Long, ub As Long
Dim numIn As Long, s As String, r As Long
numIn = col.Count
ReDim pos(1 To numIn)
ReDim lbs(1 To numIn)
ReDim ubs(1 To numIn)
ReDim lengths(1 To numIn)
t = 0
For i = 1 To numIn 'calculate # of combinations, and cache bounds/lengths
lbs(i) = LBound(col(i))
ubs(i) = UBound(col(i))
lengths(i) = (ubs(i) - lbs(i)) + 1
pos(i) = lbs(i)
t = IIf(t = 0, lengths(i), t * lengths(i))
Next i
ReDim rv(0 To t - 1) 'resize destination array
For n = 0 To (t - 1)
s = ""
For i = 1 To numIn
s = s & IIf(Len(s) > 0, SEP, "") & col(i)(pos(i)) 'build the string
Next i
rv(n) = s
For i = numIn To 1 Step -1
If pos(i) <> ubs(i) Then 'Not done all of this array yet...
pos(i) = pos(i) + 1 'Increment array index
For r = i + 1 To numIn 'Reset all the indexes
pos(r) = lbs(r) ' of the later arrays
Next r
Exit For
End If
Next i
Next n
Combine = rv
End Function
I found that from this link.
VBA - Write all possible combinations of 4 columns of data
I'm pretty sure if you do some more Googling, you can find other concepts that do pretty much the same thing.
I want this code to search the column name called((attribute value1,attribute value2..N)
If that column contains fraction values, it should convert it to decimal. I'm using this macros(VBA).
The code is working but it is converting only one column(attribute value1).
It will take more time because I have multiple columns(attribute value2...N) that have fraction values.
Please help me out I am struck here.
Sub deci()
Dim LR As Long
Dim Dash As Long
Dim Whole As Double
Dim lngDataColumn As Long
Dim pi
lngDataColumn = 4
Sheets("Sheet3").Select
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
For r = 2 To LR
s = Cells(r, lngDataColumn)
arr = Split(s, ",")
For i = LBound(arr) To UBound(arr)
Whole = 0
P = InStr(arr(i), " IN")
If P > 0 Then
Worksheet = (Left((arr(i)), P - 1))
Else
Worksheet = arr(i)
End If
Dash = InStr(Worksheet, "-")
If Dash > 0 Then
Whole = Frac(Left(Worksheet, Dash - 1))
Worksheet = Mid(Worksheet, Dash + 1)
End If
af = Right(arr(i), Len(arr(i)) - P + 1)
evfrac = Whole + Left(CStr(Evaluate(Worksheet)), 5)
' evfrac = Whole + Format(Evaluate(frac), "0.###")
ss = ss & evfrac & af & ", "
Next i
Cells(r, lngDataColumn) = Left(ss, Len(ss) - 2)
ss = ""
Next r
End Sub
Function Frac(ByVal X As String) As Double
Dim P As Integer, N As Double, Num As Double, Den As Double
X = Trim$(X)
P = InStr(X, "/")
If P = 0 Then
N = Val(X)
Else
Den = Val(Mid$(X, P + 1))
If Den = 0 Then Err.Raise 11 ' Divide by zero
X = Trim$(Left$(X, P - 1))
P = InStr(X, " ")
If P = 0 Then
Num = Val(X)
Else
Num = Val(Mid$(X, P + 1))
N = Val(Left$(X, P - 1))
End If
End If
If Den <> 0 Then
N = N + Num / Den
End If
Frac = N
End Function
The reason it's only doing one column is because that's exactly what your telling it to do with this section of the code:
lngDataColumn = 4
Sheets("Sheet3").Select
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
Because your setting lngDataColumn as a fixed figure, your code is only executed on column 4. If you want to do more columns as a loop, you need to increment this value in the same maner you are incrementing r in your for loop.
For example:
lngDataColumn = 10
Sheets("Sheet3").Select
For 4 To lngDataColumn
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
'Rest of code
Next lngDataColumn
What code would I be using to achieve this in vba, I've been trying to adapt other codes that I have seen online to my needs but it's not working out. I'll greatly appreciate any help.
I get the data in this format:
Col A Col B Col C Col D
QBC T 90125 LAK-912,323.YVS-PK,US.
QOL T 53241 LWA-324.
QEF F 31236 PKS-634,432,243.
and I would like the data to be extracted as:
Col A Col B Col C Col D
QBC T 90125 LAK-912
QBC T 90125 LAK-323
QBC T 90125 YVS-PK
QBC T 90125 YVS-US
QOL T 53241 LWA-324
QEF F 31236 PKS-634
QEF F 31236 PKS-432
QEF F 31236 PKS-243
Hope it is clear!
This sub create the list from the cell F2:
Dim LastRow As Long
Dim RowsOffset, ColsOffset, e, k As Long
Dim Str As String
Dim StrB, StrN As String
Dim Start As Long
Range("A1").Activate
LastRow = Range(ActiveCell.SpecialCells(xlLastCell).Address).Row
RowsOffset = 0
ColsOffset = 5
For e = 1 To LastRow
Str = ActiveCell.Offset(e, 3).Value
StrB = ""
StrN = ""
Start = 1
For k = 1 To Len(Str)
If Mid(Str, k, 1) = "," Then
StrN = Mid(Str, Start, k - Start)
Start = k + 1
RowsOffset = RowsOffset + 1
ActiveCell.Offset(RowsOffset, ColsOffset).Value = ActiveCell.Offset(e, 0).Value
ActiveCell.Offset(RowsOffset, ColsOffset + 1).Value = ActiveCell.Offset(e, 1).Value
ActiveCell.Offset(RowsOffset, ColsOffset + 2).Value = ActiveCell.Offset(e, 2).Value
ActiveCell.Offset(RowsOffset, ColsOffset + 3).Value = StrB & StrN
End If
If Mid(Str, k, 1) = "." Then
StrN = Mid(Str, Start, k - Start)
Start = k + 1
RowsOffset = RowsOffset + 1
ActiveCell.Offset(RowsOffset, ColsOffset).Value = ActiveCell.Offset(e, 0).Value
ActiveCell.Offset(RowsOffset, ColsOffset + 1).Value = ActiveCell.Offset(e, 1).Value
ActiveCell.Offset(RowsOffset, ColsOffset + 2).Value = ActiveCell.Offset(e, 2).Value
ActiveCell.Offset(RowsOffset, ColsOffset + 3).Value = StrB & StrN
End If
If Mid(Str, k, 1) = "-" Then
StrB = Mid(Str, Start, k - Start + 1)
Start = k + 1
End If
Next
If you want another position, change:
RowsOffset = 0 ' Rows Offset
ColsOffset = 5 ' Column Offset
If you want another sheet, the code it's a little different. YOu need to change the 8 line with Activecell with:
Sheets("Sheet2").Range("A1").Offset(RowsOffset, ColsOffset).Value = ActiveCell.Offset(e, 0).Value
The SplitAndExpand() function takes a string like in the original "Col D" and returns an array of strings as wanted in the final "Col D". Modify and call Test() from the immediate window to check the function:
Public Function SplitAndExpand(ByVal Str As String) As String()
Dim sdot() As String
Dim scomma() As Variant
Dim prefix As String
Dim result() As String
Dim i As Long
Dim j As Long
Dim n As Long
' This code is NOT the most efficient.
' 1. Split the string at ".", ignore the last empty string
Let sdot = Strings.Split(Str, ".")
If sdot(UBound(sdot)) = "" Then
ReDim Preserve sdot(0 To (UBound(sdot) - 1))
End If
' 2. For each sdot substring, split it at ","
ReDim scomma(0 To UBound(sdot))
Let n = 0
For i = 0 To UBound(sdot)
' Split
Let scomma(i) = Strings.Split(sdot(i), ",")
' Cumulate results from this split
Let n = n + UBound(scomma(i)) + 1
Next i
' 3. Build result from the prefix of the first scomma string and the
' rest of the strings. Result array is 1-based
ReDim result(1 To n)
Let n = 0
For i = 0 To UBound(scomma)
' Add the first entry and calculate prefix
Let n = n + 1
Let result(n) = scomma(i)(0)
Let prefix = Strings.Split(result(n), "-")(0) & "-"
' Assemble the rest of the entries, and save them
For j = 1 To UBound(scomma(i))
Let n = n + 1
Let result(n) = prefix & scomma(i)(j)
Next j
Next i
' 4. Return value
Let SplitAndExpand = result
End Function
Public Sub Test()
Dim a() As String
Dim k As Long
Let a = SplitAndExpand("LAK-912,323.YVS-PK,US.")
For k = LBound(a) To UBound(a)
Debug.Print a(k)
Next k
End Sub