iTextSharp - how to move section header to next page - itext

When running reports using iTextSharp we can keep all the sub categories together defining a separate PdfpTable and KeepTogether = True
This works really well with sub categories that are unlikely to go over a full page.
Is there a way to move the main categories to the next page if the sub ones do not fit on that current page?
This is what we are getting
Where Expenses starts at the end of the last main category, but the sub-categories are all on the next page
This is a snippet of how they are created...
Thanks
vTable.AddCell(AddNewTextCell(True, "REVENUE", 15, ReportFontSize, False))
vTable.AddCell(Spacer_Cell(10, 15))
For Each Row As DataRow In RevenueData
Dim vInnerTable As New PdfPTable(15)
vInnerTable.KeepTogether = True
Dim vCatID As Integer = Row("ID")
vInnerTable.AddCell(AddNewTextCell(True, Row("Name"), 15, ReportFontSize, False))
Dim vSelected() As DataRow = RevenueNomDT.Select("CatID = " & vCatID, "Position")
For Each SubRow As DataRow In vSelected
SetLeftPadding = 10
vInnerTable.AddCell(AddNewTextCell(False, SubRow("NomCode") & " " & SubRow("NomName"), 2, ReportFontSize))
Dim NomCode As Integer = SubRow("NomCode")
Dim NegValue As Integer = SubRow("NegValue")
Dim vNeg As Boolean = False
If NegValue = 1 Then
vNeg = True
End If
Dim vNomType As Integer = 0
Dim vTypes() As DataRow = NLCodes.Select("NL_Code = '" & NomCode & "'", Nothing)
For Each NominalRow As DataRow In vTypes
vNomType = NominalRow("Account_Type")
Next
SetLeftPadding = 0
'12 Columns of data
For i As Integer = 0 To 11
Dim vNomValue As Decimal = 0
Dim ReportMonth As Integer = DateDiff(DateInterval.Month, ReportStartDate, ReportDate) + 1
If ReportMonth > i Then
If vNomType = 2 Then
vNomValue = ReturnMonthlyAmount(i, NomCode, True, ReportStartDate, ReportEndDate, Current_HOA_ID, vNeg)
Else
vNomValue = ReturnMonthlyAmount(i, NomCode, False, ReportStartDate, ReportEndDate, Current_HOA_ID, vNeg)
End If
RT += vNomValue
GT = DicRevenue.Item(i)
DicRevenue.Item(i) = GT + vNomValue
Dim vAmt As Decimal = DicSubs.Item(i)
DicSubs.Item(i) = vNomValue + vAmt
vInnerTable.AddCell(AddNewCurrencyCell(vNomValue, False, False, ReportFontSize))
Else
vInnerTable.AddCell(AddNewCurrencyCell(vNomValue, False, False, ReportFontSize))
End If
Next
vInnerTable.AddCell(AddNewCurrencyCell(RT, False, False, ReportFontSize))
GT = DicRevenue(12)
DicRevenue(12) = GT + RT
DicSubs.Item(12) = RT
RT = 0
Next
SetLeftPadding = 5
'Add the total of each revenue sub header
vInnerTable.AddCell(AddNewTextCell(True, "Total " & Row("Name"), 2, ReportFontSize, False))
For i As Integer = 0 To 11
vInnerTable.AddCell(AddNewCurrencyCell(DicSubs.Item(i), True, True, ReportFontSize, False))
RT += DicSubs.Item(i)
Next
vInnerTable.AddCell(AddNewCurrencyCell(RT, True, True, ReportFontSize, False))
vTable.AddCell(NoSplitTable(vInnerTable, 15))
'Remove the DictionaryValues
For i As Integer = 0 To 12
DicSubs(i) = 0
Next
RT = 0
Next
vTable.AddCell(Spacer_Cell(10, 15))
'Add in the Totals For Revenue
vTable.AddCell(AddNewTextCell(True, "TOTAL REVENUE", 2, ReportFontSize, False))
For i As Integer = 0 To 12
vTable.AddCell(AddNewCurrencyCell(DicRevenue.Item(i), True, True, ReportFontSize, False))
Next
GT = 0
RT = 0
vTable.AddCell(Spacer_Cell(20, 15))
'============================================START OF EXPENSES ==============================================
vTable.AddCell(AddNewTextCell(True, "EXPENSES", 15, ReportFontSize, False))
vTable.AddCell(Spacer_Cell(10, 15))
Private Function NoSplitTable(TableName As PdfPTable, DataColumns As Integer) As PdfPCell
Dim vCell As New iTextSharp.text.pdf.PdfPCell(TableName)
Try
With vCell
.Border = 0
.Colspan = DataColumns
End With
Return vCell
Catch ex As Exception
EmailError(ex)
Return vCell
End Try
End Function

Turned out simpler than I thought - just add subTables for each header as well
Start of one table
Dim vRevenueTable As New PdfPTable(15)
vRevenueTable.KeepTogether = True
vRevenueTable.AddCell(AddNewTextCell(True, "REVENUE", 15, ReportFontSize, False))
vRevenueTable.AddCell(Spacer_Cell(10, 15))
For Each Row As DataRow In RevenueData
Dim vInnerTable As New PdfPTable(15)
vInnerTable.KeepTogether = True
.... end of that table
vInnerTable.AddCell(AddNewCurrencyCell(RT, True, True, ReportFontSize, False))
vRevenueTable.AddCell(NoSplitTable(vInnerTable, 15))
'Remove the DictionaryValues
For i As Integer = 0 To 12
DicSubs(i) = 0
Next
RT = 0
Next
vRevenueTable.AddCell(Spacer_Cell(10, 15))
'Add in the Totals For Revenue
vRevenueTable.AddCell(AddNewTextCell(True, "TOTAL REVENUE", 2, ReportFontSize, False))
For i As Integer = 0 To 12
vRevenueTable.AddCell(AddNewCurrencyCell(DicRevenue.Item(i), True, True, ReportFontSize, False))
Next
GT = 0
RT = 0
vRevenueTable.AddCell(Spacer_Cell(20, 15))
vTable.AddCell(NoSplitTable(vRevenueTable, 15))

Besides using keeptogether-tables you can force page breaks by calling
Document.NewPage() or wrap your tables with Chapters and Sections instead of creating one big table container.
(4.1.6.0)

Related

Cannot get my chart ‘stacked’ using a Calc macro

Somehow I cannot get my chart to ‘stack’. For reasons explained below I first prepare a standard chart in a macro called ‘ChartsGeneral’. Based on some settings on my ‘Charts’ worksheet, it then calls a specific second macro, e.g. ‘ChartBuildStatus’. In this second macro I generate the category and data-series, and adjust the settings of the standard chart as necessary.
When I try to get a stacked chart via ‘createInstance(“com.sun.star.chart.StackableDiagram”)’ nothing changes. I have studied the documentation and several forums, but I have no clue what I am missing. Code below.
Configuration details
Version: 7.4.3.2 (x64) / LibreOffice Community
CPU threads: 12; OS: Windows 10.0 Build 19045; Locale: nl-NL (nl_NL); UI: en-US
OK, here it goes… Please have some mercy on a poor old non-programmer nerd.
Background
Over the years I collected a rather large set of Excel spreadsheets with VBA macros for my personal finances. This year I decided to migrate them all to LibreOffice, as part of my wider migration from Windows to Linux. I am not a programmer, so I decided to use BASIC as it would be closest to VBA.
One of my spreadsheets tracks progress on our home mortgage. I keep track of all payments on interest and principal. As we are paying down extra with a fixed monthly payment and a ‘snowball’ (all savings go back as payments to the principal) the spreadsheet also calculates the expected next snowball payment, as well as a prognosis for the remainder of the mortgage. That all works fine.
The key worksheets in my Mortgage spreadsheet are ‘Months’, where I store all the data of past payments, and ‘Prognosis’, which holds a copy of ‘Months’ but also a prognosis for every month in the future.
I am now down to the last block of functionality: reporting. This is mainly a collection of charts that show the history, current status and prognosis for my mortgage based on the data in Months and Prognosis. For this I use a dedicated worksheet called ‘Charts’ in my spreadsheet. Here I can select a Chart Type from a dropdown-list, as well as some date or period related settings (I use named fields for this). See a partial screenshot below.
Partial Screenshot of Charts worksheet
When I press the ‘Update Chart’ button on my Charts worksheet, a macro called ‘ChartsGeneral’ is triggered. In this macro:
I use the date or period related settings to calculate the starting row and ending row for the data series
I then generate an empty standard linechart called ‘AdminChart’ on the Charts worksheet, with settings for the axes, the formatting, and everything
I call a second macro based on the ChartType value on Charts. In the above example the chart is called ‘Opbouw Stand van Zaken’, so I call a second macro called ChartBuildStatus.
The code for ChartsGeneral can be found below
Sub ChartsGeneral()
'Manages the Charts worksheet
'Set Worksheets
wshC = ThisComponent.Sheets.getByName("Charts")
wshM = ThisComponent.Sheets.getByName("Months")
wshP = ThisComponent.Sheets.getByName("Prognosis")
wshS = ThisComponent.Sheets.getByName("Settings")
'Define Colours
cBlack = RGB(0, 0, 0)
cGray01 = RGB(50, 50, 50)
cGray02 = RGB(191, 191, 191)
cWhite = RGB(255, 255, 255)
cDarkRed = RGB(192, 0, 0)
cPinkiDEAL = RGB(204, 0, 102) 'iDeal
cGreenCash = RGB(112, 173, 71) 'Cash Green
cBluePin = RGB(41, 65, 113) 'PIN Blue
cBlueContactless = RGB(58, 125, 193) 'Contactloos Light Blue
cOrangeVisa = RGB(246, 155, 14) 'Visa Orange
'Set Parameters
'Prognosis
ColumnOriginal = 18 'Original Rest Mortgage
ColumnRest = 17 'Actual Rest Mortgae
ColumnPaid = 16 'Reeds afgelost
ColumnPrognosis = 21 'Prognosis Rest Mortgage
ColumnInterestSavedPrognosis = 23 'Bespaarde rente prognose
ColumnInterestSaved = 26 'Bespaarde rente
ColumnExtraTotal = 14 'Column total extra cumulative
ColumnPercent = 24
ColumnPercentPrognosis = 25
'Months
XASColumn = 2
ColumnExtra = 13 'Extra repayment column
ColumnRegular = 12 'Regular repayment column
ColumnInterest = 11 'Interest payment column
ColumnMonthInterest = 3 'Interest payment column
ColumnMonthRegular = 4 'Regular repayment column
ColumnMonthTotal = 9 'Total Monthly repayment column
ColumnSnowball = 7 'Snowball per month column
ColumnWOZ = 17 'WOZ column
ColumnMortgage = 16 'Rest of mortgage column
ColumnVasteLasten = 5 'Regular Interest and Depreciation
ColumnLTV = 21 'LTV Ratio
ColumnPercentageRest = 24 'Percentage Rest Mortgage Paid This Month
ColumnWOZpercentage = 22 'WOZ percentage column
ColumnMortgagePercentage = 26 'Rest of mortgage percentage column
'X-As Values
LastMonthRow = getLastContentIndex("Months", 3)
If wshM.getCellByPosition(1, LastMonthRow).Value = (ThisComponent.NamedRanges.getByName("ChartMonth").getReferredCells.Value + 1) Then
LastMonthRow = LastMonthRow - 1
End If
LastMonth = wshM.getCellByPosition(1, LastMonthRow).Value
LastYear = wshM.getCellByPosition(0, LastMonthRow).Value
xStartRow = 3
xEndRow = LastMonthRow
If ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String = "1Y" Then
StartYear = LastYear - 1
StartMonth = LastMonth + 1
If StartMonth = 13 Then
StartYear = StartYear + 1
StartMonth = 1
End If
For i = xStartRow To LastMonthRow
If wshM.getCellByPosition(0, i).Value = StartYear And wshM.getCellByPosition(1, i).Value = StartMonth Then
xStartRow = i
Exit For
End If
Next i
End If
If ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String = "2Y" Then
StartYear = LastYear - 2
StartMonth = LastMonth + 1
If StartMonth = 13 Then
StartYear = StartYear + 1
StartMonth = 1
End If
For i = xStartRow To LastMonthRow
If wshM.getCellByPosition(0, i).Value = StartYear And wshM.getCellByPosition(1, i).Value = StartMonth Then
xStartRow = i
Exit For
End If
Next i
End If
If ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String = "3Y" Then
StartYear = LastYear - 3
StartMonth = LastMonth + 1
If StartMonth = 13 Then
StartYear = StartYear + 1
StartMonth = 1
End If
For i = xStartRow To LastMonthRow
If wshM.getCellByPosition(0, i).Value = StartYear And wshM.getCellByPosition(1, i).Value = StartMonth Then
xStartRow = i
Exit For
End If
Next i
End If
If ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String = "5Y" Then
StartYear = LastYear - 5
StartMonth = LastMonth + 1
If StartMonth = 13 Then
StartYear = StartYear + 1
StartMonth = 1
End If
For i = xStartRow To LastMonthRow
If wshM.getCellByPosition(0, i).Value = StartYear And wshM.getCellByPosition(1, i).Value = StartMonth Then
xStartRow = i
Exit For
End If
Next i
End If
If ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String = "10Y" Then
StartYear = LastYear - 10
StartMonth = LastMonth + 1
If StartMonth = 13 Then
StartYear = StartYear + 1
StartMonth = 1
End If
For i = xStartRow To LastMonthRow
If wshM.getCellByPosition(0, i).Value = StartYear And wshM.getCellByPosition(1, i).Value = StartMonth Then
xStartRow = i
Exit For
End If
Next i
End If
If ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String = "15Y" Then
StartYear = LastYear - 15
StartMonth = LastMonth + 1
If StartMonth = 13 Then
StartYear = StartYear + 1
StartMonth = 1
End If
For i = xStartRow To LastMonthRow
If wshM.getCellByPosition(0, i).Value = StartYear And wshM.getCellByPosition(1, i).Value = StartMonth Then
xStartRow = i
Exit For
End If
Next i
End If
If ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String = "20Y" Then
StartYear = LastYear - 20
StartMonth = LastMonth + 1
If StartMonth = 13 Then
StartYear = StartYear + 1
StartMonth = 1
End If
For i = xStartRow To LastMonthRow
If wshM.getCellByPosition(0, i).Value = StartYear And wshM.getCellByPosition(1, i).Value = StartMonth Then
xStartRow = i
Exit For
End If
Next i
End If
'Global Variable for BlogMarkers
ChartStartRow = StartRow
'Generate New Chart
oCharts = wshC.Charts
If oCharts.Count <> 0 then
For i = 0 to oCharts.Count-1
oChart = oCharts.getByIndex(i)
If oChart.name = "AdminChart" then
oCharts.removeByName("AdminChart")
End If
Next i
End If
Dim oRange as Object
Dim oRangeAddress(1) As New com.sun.star.table.CellRangeAddress
Dim oRect As New com.sun.star.awt.Rectangle
Dim cTitle as String
'Define Point and Size in order to change Position and Size of Chart Objects
Dim Pos_Chart As New com.sun.star.awt.Point
Dim Pos_Title As New com.sun.star.awt.Point
Dim Pos_SubTitle As New com.sun.star.awt.Point
Dim Pos_xTitle As New com.sun.star.awt.Point
Dim Pos_yTitle As New com.sun.star.awt.Point
Dim Pos_Legend As New com.sun.star.awt.Point
Dim Size_Chart As New com.sun.star.awt.Size
Dim Size_Title As New com.sun.star.awt.Size
Dim Size_SubTitle As New com.sun.star.awt.Size
Dim Size_xTitle As New com.sun.star.awt.Size
Dim Size_yTitle As New com.sun.star.awt.Size
Dim Size_Legend As New com.sun.star.awt.Size
oRange = thisComponent.getCurrentSelection.getRangeAddress
oRect.Width = 34000
oRect.Height = 19500
oRect.X = 8650
oRect.Y = 20
cTitle = "AdminChart"
oCharts.addNewByName(cTitle,oRect,oRangeAddress(), TRUE, TRUE)
oChart = oCharts.getByName(cTitle).embeddedObject
oChart.Diagram = oChart.createInstance("com.sun.star.chart.LineDiagram") 'LineDiagram
oDiagram = oChart.Diagram
'Change position and size of chart area in rectangle
oChart.RefreshAddInAllowed = True
Pos_Chart.X = 700
Pos_Chart.Y = 1600
Size_Chart.Width = oRect.Width - 1500
Size_Chart.Height = oRect.Height - 2500
oDiagram.setPosition( Pos_Chart )
oDiagram.setSize( Size_Chart )
'Title and Subtitle of Chart
'oChart.SplineType = 0
oChart.HasMainTitle = True
oChart.Title.String = cTitle
oChart.Title.CharColor = cBlack
oChart.Title.CharFontName = "Liberation Sans"
oChart.Title.CharHeight = 16 ' Font Size
oChart.Title.CharWeight = 0 ' Bold in %
oChart.Title.CharPosture = 0 ' Italics = 1
oChart.HasSubTitle = False
'oChart.SubTitle.String = "Testing the waters"
'oChart.SubTitle.CharColor = cBlue
'oChart.SubTitle.CharFontName = "Liberation Sans"
'oChart.SubTitle.CharHeight = 12 ' Font Size
'oChart.SubTitle.CharWeight = 100 ' Bold in %
'oChart.SubTitle.CharPosture = 0 ' Italics
'Chart Area colours
oDiagram.Wall.FillStyle = com.sun.star.drawing.FillStyle.SOLID
oDiagram.Wall.FillColor = cWhite 'Chart Area Colour
oDiagram.Wall.LineStyle = com.sun.star.drawing.FillStyle.SOLID
oDiagram.Wall.LineColor = cBlack 'Chart Area Border Colour
oDiagram.Wall.LineWidth = 20
oChart.Area.FillStyle = com.sun.star.drawing.FillStyle.SOLID
oChart.Area.FillColor = cWhite 'Full Area Colour
'Horizontal Major Grid Lines
oDiagram.HasYAxisGrid = True
oDiagram.YMainGrid.LineStyle = com.sun.star.drawing.FillStyle.SOLID
oDiagram.YMainGrid.LineColor = cGray02
oDiagram.YMainGrid.LineWidth = 20
'Vertical Major Grid Lines
oDiagram.HasXAxisGrid = False
oDiagram.XMainGrid.LineStyle = com.sun.star.drawing.FillStyle.SOLID
oDiagram.XMainGrid.LineColor = cGray02
oDiagram.XMainGrid.LineWidth = 20
'X-Axis
oDiagram.HasXAxis = True
oDiagram.HasXAxisDescription = True
oDiagram.HasXAxisTitle = True
oXaxis = oDiagram.getXAxis()
oXaxis.AxisTitle.String = "X-Values"
oXaxis.AxisTitle.CharFontName = "Liberation Sans"
oXaxis.AxisTitle.CharColor = cBlack
oXaxis.AxisTitle.CharHeight = 11 ' Font Size
oXaxis.AxisTitle.CharWeight = 0 ' Bold in %
oXaxis.AxisTitle.CharPosture = 0 ' Italics = 1
oXaxis.AutoMin = True
oXaxis.AutoMax = True
'oXaxis.Min = 1
'oXaxis.Max = 5
oXaxis.CharColor = cBlack
oXaxis.CharFontName = "Liberation Sans"
oXaxis.CharHeight = 10 ' Font Size
oXaxis.CharWeight = 100 ' Bold in %
oXaxis.CharPosture = 0 ' Italics
oXaxis.LineColor = cBlack
oXaxis.LineWidth = 20
'Primary Y-Axis
oDiagram.HasYAxis = True
oDiagram.HasYAxisDescription = True
oDiagram.HasYAxisTitle = False
oDiagram.HasYAxis = True
oYaxis = oDiagram.getYAxis()
oYaxis.AxisTitle.String = "Y-Values"
oYaxis.AxisTitle.CharFontName = "Liberation Sans"
oYaxis.AxisTitle.CharColor = cBlack
oYaxis.AxisTitle.CharHeight = 11 ' Font Size
oYaxis.AxisTitle.CharWeight = 0 ' Bold in %
oYaxis.AxisTitle.CharPosture = 0 ' Italics = 1
oYaxis.AutoMin = False
oYaxis.AutoMax = False
oYaxis.Min = 0
oYaxis.Max = 2000
oYaxis.StepMain = 250
oYaxis.CharColor = cBlack
oYaxis.CharFontName = "Liberation Sans"
oYaxis.CharHeight = 10 ' Font Size
oYaxis.CharWeight = 0 ' Bold in %
oYaxis.CharPosture = 0 ' Italics
oYaxis.LineColor = cBlack
oYaxis.LineWidth = 20
oYaxis.LinkNumberFormatToSource = False
oYaxis.NumberFormat = "114"
oChart.HasLegend = 1
oLegend = oChart.getLegend()
oLegend.AutomaticPosition = True
oLegend.Alignment = com.sun.star.chart.ChartLegendPosition.BOTTOM
oLegend.CharHeight = 10 ' Font Size
oLegend.CharWeight = 0 ' Bold in %
oLegend.CharFontName = "Liberation Sans"
oLegend.FillColor = cWhite
oLegend.LineColor = cWhite
oLegend.CharColor = cBlack
oLegend.CharPosture = 0 'Italics
oDiagram.Lines = True
oDiagram.LineColor = cDarkRed
oDiagram.LineWidth = 20
'oChart.DataSourceLabelsInFirstColumn = True
'oChart.DataSourceLabelsInFirstRow = False
'Call Chart Procedure
If ThisComponent.NamedRanges.getByName("ChartType").getReferredCells.String = "Opbouw Stand van Zaken" Then
cTitle = "Opbouw Eigen Woning " & ThisComponent.NamedRanges.getByName("ChartPeriod").getReferredCells.String
Call ChartBuildStatus(xStartRow, xEndRow, cTitle)
End If
End Sub
Once the macro ChartBuildStatus is called, that macro contains the following actions:
I change the chart type of AdminChart to AreaDiagram. That shows up correctly on my screen.
I then try to make it a stacked diagram. But it won’t…
After that, I change some formatting characteristics of the chart, like axis titles and number formats
And I generate the category and data series calling on two other macro’s, CreateDataSequence() and CreateDataSeries_Chart(). I don’think they are the problem, they work correctly with other non-stacked line charts and the series
I have tried a number of things, including moving the stacking code to the end of the macro. But I cannot get it to work correctly. I must be overlooking something or doing something very stupid. So after literally days of trying I am pinning my hopes on the community. Anybody who can shed some light on this?
Sub ChartBuildStatus(xStartRow As Long, xEndRow As Long, cTitle As String)
'Define Colours
cBlack = RGB(0, 0, 0)
cGray01 = RGB(50, 50, 50)
cGray02 = RGB(191, 191, 191)
cWhite = RGB(255, 255, 255)
wshC = ThisComponent.Sheets.getByName("Charts")
wshM = ThisComponent.Sheets.getByName("Months")
oCharts = wshC.Charts
oChart = oCharts.getByName("AdminChart").embeddedObject
oChart.Diagram = oChart.createInstance("com.sun.star.chart.AreaDiagram")
'Stackable Diagram
oChart.Diagram = oChart.createInstance("com.sun.star.chart.StackableDiagram")
oDiagram = oChart.getDiagram()
oChart.setDiagram(oDiagram)
oDiagram = oChart.getDiagram()
With oDiagram
.Stacked = True
.Percent = False
.Vertical = False
End With
ChartUnit = 50000
'Specific Chart Adjustments
oXaxis = oDiagram.getXAxis()
oYaxis = oDiagram.getYAxis()
'Ymax And Ymin
oYaxis.AutoMax = True
oYaxis.Min = 0
'Chart details
oChart.Title.String = cTitle
oDiagram.HasXAxisTitle = False
oYaxis.AxisTitle.String = "EUR"
oYaxis.StepMain = ChartUnit
oYaxis.NumberFormat = "115" ' #,##0
'Data Series Generator
oDataProvider = oChart.getDataProvider()
oDiagram = oChart.getFirstDiagram()
oCooSys = oDiagram.getCoordinateSystems()
oCoods = oCooSys(0) ' this chart has only a coordinate system
oChartTypes = oCoods.getChartTypes() ' chart type one by one
oChartType = oChartTypes(0)
'Data Ranges
xEndRow = getLastContentIndex ("Months", 3 )
Xrange = "Months.C" & (xStartRow + 1) & ":C" & (xEndRow + 1) 'yyyymm
Y1range = "Months.S" & (xStartRow + 1) & ":S" & (xEndRow + 1) 'Overwaarde
Y2range = "Months.T" & (xStartRow + 1) & ":T" & (xEndRow + 1) 'Eigen Geld
Y3range = "Months.M" & (xStartRow + 1) & ":M" & (xEndRow + 1) 'Reguliere Aflossing
Y4range = "Months.N" & (xStartRow + 1) & ":N" & (xEndRow + 1) 'Extra Aflossing
Y5range = "Months.Q" & (xStartRow + 1) & ":Q" & (xEndRow + 1) 'Restant Hypotheek
'Prepare for Data Series
oDataProvider = oChart.getDataProvider()
oDiagram = oChart.getFirstDiagram()
oCooSys = oDiagram.getCoordinateSystems()
oCoods = oCooSys(0) ' this chart has only a coordinate system
oChartTypes = oCoods.getChartTypes() ' chart type one by one
oChartType = oChartTypes(0)
'X-Axis Data series
dim categorySequence as object, categoryRange as string
dim coordinateSystem as object, axis as object
dim scaleData as new com.sun.star.chart2.ScaleData
categorySequence = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")
categorySequence.setValues(CreateDataSequence(oDataProvider, Xrange, "categories"))
coordinateSystem = oDiagram.getCoordinateSystems()(0)
axis = coordinateSystem.getAxisByDimension(0, 0)
scaleData = axis.getScaleData()
scaleData.Categories = categorySequence
axis.setScaleData(scaleData)
'Y-Axis Data series
oDataSeriesList = oChartType.getDataSeries()
Dim oNewDataSeriesList(4) As Object ' new data series
oSeries1 = CreateDataSeries_Chart(oDataProvider, Xrange, Y1range, "Overwaarde")
oSeries1.Color = RGB(197, 224, 180)
oSeries1.LineWidth = 60
oNewDataSeriesList(0) = oSeries1
oSeries2 = CreateDataSeries_Chart(oDataProvider, Xrange, Y2range, "EigenGeld")
oSeries2.Color = RGB(0, 176, 80)
oSeries2.LineWidth = 60
oNewDataSeriesList(1) = oSeries2
oSeries3 = CreateDataSeries_Chart(oDataProvider, Xrange, Y3range, "Aflossing")
oSeries3.Color = RGB(146, 208, 80)
oSeries3.LineWidth = 60
oNewDataSeriesList(2) = oSeries3
oSeries4 = CreateDataSeries_Chart(oDataProvider, Xrange, Y4range, "AflossingExtra")
oSeries4.Color = RGB(255, 215, 0)
oSeries4.LineWidth = 60
oNewDataSeriesList(3) = oSeries4
oSeries5 = CreateDataSeries_Chart(oDataProvider, Xrange, Y5range, "RestHypotheek")
oSeries5.Color = RGB(192, 0, 0)
oSeries5.LineWidth = 60
oNewDataSeriesList(4) = oSeries5
'Update chart (only the charttype is updated)
oChartType.setDataSeries(oNewDataSeriesList)
End Sub
On the left the chart as it looks now in my LibreOffice Calc spreadsheet, on the right the chart as I want it to look based on my current Excel sheet.
Left: LibreOffice / Right: Excel (how I want it)
For the sake of completeness, please find the additional macro’s CreateDataSequence() and CreateDataSeries_Chart() below.
CreateDataSequence()
Function CreateDataSequence( oDataProvider As Object, sRangeRepresentation As String, sRole As String ) As Object
Dim oDataSequence As Object
On Error GoTo Handler
' create .chart2.data.DataSequence from range representation
oDataSequence = oDataProvider.createDataSequenceByRangeRepresentation(sRangeRepresentation)
If NOT IsNull(oDataSequence) Then
oDataSequence.Role = sRole
End If
Handler:
CreateDataSequence = oDataSequence
End Function
CreateDataSeries_Chart()
Function CreateDataSeries_Chart( oDataProvider As Object, sXRangeRepresentation As String, sYRangeRepresentation As String, sLabelRangeRepresentation As String ) As Object
Dim oNewDataSeries As Object
oNewDataSeries = CreateUnoService("com.sun.star.chart2.DataSeries")
Dim oData(1) As Object ' x and y: .chart2.data.XLabeledDataSequence
' Y
oDataY = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")
oSequenceY = CreateDataSequence(oDataProvider, sYRangeRepresentation, "values-y")
If NOT IsNull(oSequenceY) Then
oDataY.setValues(oSequenceY)
If NOT ((IsMissing(sLabelRangeRepresentation)) AND (sLabelRangeRepresentation <> "")) Then
oSequenceLabel = CreateDataSequence(oDataProvider, sLabelRangeRepresentation, "label") ' ""
oDataY.setLabel(oSequenceLabel) ' oSequenceLabel label is used as name
End If
End If
' X
oDataX = CreateUnoService("com.sun.star.chart2.data.LabeledDataSequence")
oSequenceX = CreateDataSequence(oDataProvider, sXRangeRepresentation, "values-x")
If NOT IsNull(oSequenceX) Then
oDataX.setValues(oSequenceX)
End If
' set x and y data to series
aData = Array(oDataY, oDataX)
oNewDataSeries.setData(aData)
CreateDataSeries_Chart = oNewDataSeries
End Function

Remove Marks on Charts

I have a problem with my code, I want to evaluate a Report with Charts.
What my Macro currently does is, Create for every single column a Row for a nominal, upper, lower tolerance. Then It creates with this values a chart.
After this it starts with the Sorting and then it removes the Marker Points, but here my Problems already start.
I would like to create the charts later for example on pos A100 or A50 or something.
Then the Marker Points, I would like to keep the Points on the result line but not on the 3 created, but I found no way 
Remove the Markers, but it removes all, i would really like to remove them only for
FullSeriesCollection(2).format.Line
FullSeriesCollection(3).format.Line
FullSeriesCollection(4).format.Line
Would be nice if someone would have an idea.. :)
Thanks in advance,
' Unload UFormTools
UFormTools.Hide
Application.ScreenUpdating = False
Sheets("Original Values").Select
Dim lngC As Long, lngR As Long
Dim i As Long
Dim c As Byte
Application.ScreenUpdating = False
With ActiveSheet
lngC = (.Cells(17, 4).End(xlToRight).Column - 4) * 4
For i = 4 To lngC Step 4
lngR = .Cells(.Rows.Count, i).End(xlUp).Row
For c = 1 To 3
.Columns(i + c).EntireColumn.Insert
Next c
.Cells(17, i).AutoFill Destination:=.Range(.Cells(17, i), .Cells(17, i + 3)), Type:=xlFillCopy
.Range(.Cells(28, i + 1), .Cells(lngR, i + 1)).Value = .Cells(18, i).Value
.Range(.Cells(28, i + 2), .Cells(lngR, i + 2)).Value = .Cells(18, i).Value + .Cells(19, i).Value
.Range(.Cells(28, i + 3), .Cells(lngR, i + 3)).Value = .Cells(18, i).Value + .Cells(20, i).Value
.Shapes.AddChart2(332, xlLineMarkers).Select
With ActiveChart
.SetSourceData Source:=Union(ActiveSheet.Range(ActiveSheet.Cells(17, i), ActiveSheet.Cells(17, i + 3)), _
ActiveSheet.Range(ActiveSheet.Cells(28, i), ActiveSheet.Cells(lngR, i + 3)))
' .Legend.Delete
.ChartTitle.Text = ActiveSheet.Cells(17, i).Value
.ChartTitle.format.TextFrame2.TextRange.Characters.Text = ActiveSheet.Cells(17, i).Value
With .ChartTitle.format.TextFrame2.TextRange.Characters(1, Len(ActiveSheet.Cells(17, i).Value)).ParagraphFormat
.TextDirection = msoTextDirectionLeftToRight
.Alignment = msoAlignCenter
End With
With .FullSeriesCollection(3).format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
With .FullSeriesCollection(4).format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
With .FullSeriesCollection(2).format.Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0
.Transparency = 0
.Visible = msoTrue
.DashStyle = msoLineDash
.Weight = 1.5
End With
With .FullSeriesCollection(1).format.Line
.Visible = msoTrue
.Weight = 3
End With
.FullSeriesCollection(1).Smooth = True
.Axes(xlValue).MinimumScaleIsAuto = True
.Axes(xlValue).MinimumScaleIsAuto = True
End With
Next i
End With
' Sort and Arrange Charts, but another Position to Start would be nice.. (for example A100)
Dim MyWidth As Single, MyHeight As Single
Dim NumWide As Long
Dim iChtIx As Long, iChtCt As Long
MyWidth = 300
MyHeight = 200
NumWide = 4
iChtCt = ActiveSheet.ChartObjects.Count
For iChtIx = 1 To iChtCt
With ActiveSheet.ChartObjects(iChtIx)
.Width = MyWidth
.Height = MyHeight
.Left = ((iChtIx - 1) Mod NumWide) * MyWidth
.Top = Int((iChtIx - 1) / NumWide) * MyHeight
End With
Next
' Remove the Markers, but it removes all, i would really like to remove them only for
' FullSeriesCollection(2).format.Line
' FullSeriesCollection(3).format.Line
' FullSeriesCollection(4).format.Line
Dim cht As ChartObject
Dim srs As Series
Dim MarkerCount As Long
For Each cht In ActiveSheet.ChartObjects
cht.Activate
For Each srs In ActiveChart.SeriesCollection
If srs.MarkerStyle <> xlMarkerStyleNone Then
srs.MarkerStyle = xlMarkerStyleNone
MarkerCount = MarkerCount + 1
End If
Next srs
Next cht
Range("A1").Select
Application.ScreenUpdating = True

How to copy data into cells, make a table and add more data to it

UI looks like:
Account:Wessex bank plc
Income: 200€
Costs:
Date: 28.02.2021
Output should be a list below in the cells:
Date: | Account: | Income: | Costs: |
28.02.2021 | Wessex Bank plc | 200€ |
28.02.2021 | Food | - | 175€ |
Hint: I would like to have a list of 5-7 bookings and when
making a new booking the latest booking is going to be at the top position and the first booking in the last row, like when the table starts at row 13 and I make 5 bookings with different accounts, the first booking will be at 17 in the end.
this is copying the content in the table
Sub MyBuchenMakro
Dim currDoc As Object
Dim currSheet As Object
Dim curr Cell As Object
Dim destCell As Object
Dim oDate As Date
Dim einnahmen As Currency
Dim ausgaben As Currency
currDoc = ThisComponent
currSheet = currDoc.sheets(0)
currCell = currSheet.getCellByPosition(1, 5)
destCell = currSheet.getCellByPosition(1, 12)
destCell.String = currCell.String
currCell = currSheet.getCellByPosition(1, 6)
destCell = currSheet.getCellByPosition(2, 12)
destCell.setValue(CCur(currCell.getValue()))
currCell = currSheet.getCellByPosition(1, 7)
destCell = currSheet.getCellByPosition(3, 12)
destCell.setValue(CCur(currCell.getValue()))
currCell = currSheet.getCellByPosition(1, 8)
destCell = currSheet.getCellByPosition(0, 12)
destCell.setValue(CDate(currCell.getValue()))
For i = 160 To 13 Step 1
destCell = currSheet.getCellByPosition(0, i)
If destCell == "" Then
GoTo Continue
End if
destCell = currSheet.getCellByPosition(0,i+1)
destCell.setValue(CDate(currCell.getValue()))
currCell = currSheet.getCellByPosition(1,i)
destCell = currSheet.getCellByPosition(1,i+1)
destCell.String = currCell.String
currCell = currSheet.getCellByPosition(2,i)
destCell = currSheet.getCellByPosition(2,i+1)
destCell.setValue(CCur(currCell.getValue()))
currCell = currSheet.getCellByPosition(3,i)
destCell = currSheet.getCellByPosition(3,i+1)
destCell.setValue(CCur(currCell.getValue()))
Next i
End Sub
[1]: https://i.stack.imgur.com/Mw7pJ.png
In fact, it is written a little shorter:
Option Explicit
Sub BuchenMacro
Dim oCurrentController As Variant ' get Activesheet and select first cell of form
Dim oSheet As Variant ' Activesheet
Dim oSourceRange As Variant ' Range B6:B9 - fields of input form
Dim oDataArray As Variant ' Data from input form
oCurrentController = ThisComponent.getCurrentController()
oSheet = oCurrentController.getActiveSheet()
Rem Range with data
oSourceRange = oSheet.getCellRangeByName("B6:B9")
Rem Data from this range as "array of arrays"
oDataArray = oSourceRange.getDataArray()
Rem To prevent insert empty row - validate source cells:
Rem If 3 first cells are empty then stop:
If Trim(oDataArray(0)(0))+Trim(oDataArray(1)(0))+Trim(oDataArray(2)(0)) = "" Then Exit Sub
Rem "Transpose" source data to single row:
oDataArray = Array(Array(oDataArray(3)(0), oDataArray(0)(0), oDataArray(1)(0), oDataArray(2)(0)))
Rem Insert new row after header and shift all other rows down:
oSheet.getRows().insertByIndex(12, 1)
Rem Paste data from form to this new row
oSheet.getCellRangeByPosition(0, 12, 3, 12).setDataArray(oDataArray)
Rem Clear input cells to prevent duplicates
Rem (Only the data is cleared, the formulas remain in place.
Rem Put in cell B9 the formula =TEXT(TODAY();"DD.MM.YYYY")
Rem and it will always show the current date)
oSourceRange.clearContents(7)
Rem Select first cell
oCurrentController.Select(oSheet.getCellByPosition(1,5))
Rem Deselect cell
oCurrentController.Select(ThisComponent.createInstance("com.sun.star.sheet.SheetCellRanges"))
End Sub

Link Variable to Label on another form in vb

I have a small program for some college coursework, i have to enter data of the gender and age of a group of people then work out the male and female percent and the child and adult percent. The bit i am stuck with is i want to display my results on labels on a separate form. Here is my code:
Public Class Form1
Dim TotalGender As Integer
Dim TotalAge As Integer
Dim MaleCount As Integer
Dim FemaleCount As Integer
Dim ChildCount As Integer
Dim AdultCount As Integer
Dim MalePercent As Single
Dim FemalePercent As Single
Dim AdultPercent As Single
Dim ChildPercent As Single
Private Sub btnSub_Click(sender As Object, e As EventArgs) Handles btnSub.Click
If cmbGender.Text = "Male" Then
MaleCount += 1
End If
If cmbGender.Text = "Female" Then
FemaleCount += 1
End If
If cmbAge.Text > 18 Then
ChildCount += 1
End If
If cmbAge.Text <= 18 Then
AdultCount += 1
End If
End Sub
Private Sub btnResults_Click(sender As Object, e As EventArgs) Handles btnResults.Click
Form2.Show()
MalePercent = MaleCount / TotalGender * 100
FemalePercent = FemaleCount / TotalGender * 100
AdultPercent = AdultCount / TotalAge * 100
ChildPercent = ChildCount / TotalAge * 100
End Sub
Private Sub btnReset_Click(sender As Object, e As EventArgs) Handles btnReset.Click
TotalGender = 0
TotalAge = 0
MaleCount = 0
FemaleCount = 0
ChildCount = 0
AdultCount = 0
MalePercent = 0
FemalePercent = 0
AdultPercent = 0
ChildPercent = 0
End Sub
End Class
My second form has all the labels already placed and i know how to display results on a label, i just don't know how to transfer the results across to another form
You can write on form 1 .It shows your results on form2
Form2.Label1.Text = AdultCount
Form2.Show()

Can I perform a count distinct query on values selected from a listbox?

I have a select distinct query that works find on selected fields from a listbox. However I would like it to be a count distinct and I can't seem to get the code right. Below is my working code for select distinct. Thanks in advance for any assistance I've searched for count distinct questions but I don't see any specific to listbox selections.
Private Sub CmdDistinctVal_Click()
Dim cn1 As ADODB.Connection
Dim rs1 As New ADODB.Recordset
Dim cmd1 As New ADODB.Command
Dim varItem As Variant
Dim aFields() As aArray
Dim NumRows As Integer
Dim NumFields As Integer
Dim colcount As Integer
Dim colwidths As String
Dim strRow As String
Dim cnt1 As Integer
Dim cnt2 As Integer
'On Error GoTo Err_ CmdDistinctVal_Click
'cmd1.ActiveConnection = CurrentProject.Connection
Me.DistinctResultsFldVal.RowSource = ""
ReDim aFields(50)
For cnt1 = 1 To 50
ReDim aFields(cnt1).fValue(6000)
Next
NumRows = 0
colcount = 0
For Each varItem In Me!ResultsFieldList.ItemsSelected
colcount = colcount + 1
aFields(colcount).fName = Me!ResultsFieldList.ItemData(varItem)
NumFields = 0
rs1.Open "SELECT DISTINCT " & Me!ResultsFieldList.ItemData(varItem) & "
FROM [Results Report]", CurrentProject.Connection, adOpenKeyset, adLockOptimistic
If rs1.RecordCount > NumRows Then NumRows = rs1.RecordCount
strRow = strRow & Me!ResultsFieldList.ItemData(varItem) & ";"
While Not rs1.EOF
NumFields = NumFields + 1
If NumFields > NumRows Then
NumRows = NumFields
End If
aFields(colcount).fValue(NumFields) = rs1(0) & ""
rs1.MoveNext
Wend
rs1.Close
Next varItem
strRow = Left(strRow, Len(strRow) - 1)
Me.DistinctResultsFldVal.ColumnCount = colcount
Me.DistinctResultsFldVal.ColumnWidths = Mid(colwidths, 2)
Me.DistinctResultsFldVal.AddItem (strRow)
For cnt1 = 1 To NumRows
strRow = ""
For cnt2 = 1 To colcount
If aFields(cnt2).fValue(cnt1) = "" Then
strRow = strRow & ";"
Else
strRow = strRow & aFields(cnt2).fValue(cnt1) & ";"
End If
Next
strRow = Left(strRow, Len(strRow) - 1)
Me.DistinctResultsFldVal.AddItem (strRow)
Next
'Err_ CmdDistinctVal_Click:
'MsgBox "All null values were found in one or more of your selected fields"
End Sub