How to Export Datagridview to Excel Workbook - excel

I am running into an issue while trying to export a Datagridview to an excel workbook. I have 2 different codes, the first one throws an error about a null value and the second exports the data to excel but its missing the headers and a column or 2. Any direction you can give would be mush appreciated.
This one throws a Null Error
'Creating DataTable
Dim dt As New DataTable()
'Adding the Columns
For Each column As DataGridViewColumn In DataGridView1.Columns
dt.Columns.Add(column.HeaderText, column.ValueType)
Next
'Adding the Rows
For Each row As DataGridViewRow In DataGridView1.Rows
dt.Rows.Add()
For Each cell As DataGridViewCell In row.Cells
dt.Rows(dt.Rows.Count - 1)(cell.ColumnIndex) = cell.Value.ToString()
Next
Next
'Exporting to Excel
Dim folderPath As String = "C:\Users\" & UserName & "\Desktop\SkyNet Exports"
If Not My.Computer.FileSystem.DirectoryExists(folderPath) Then
My.Computer.FileSystem.CreateDirectory(folderPath)
End If
Dim wb As New Excel.Application()
wb.Worksheets.Add(dt, "Skills")
wb.SaveAs(folderPath & Convert.ToString("SkyNet Export.xlsx"))
And this one exports to excel but with missing columns and no headers
Private Sub ExportToExcel()
Dim ExcelApp As Object, ExcelBook As Object
Dim ExcelSheet As Object
Dim i As Integer
Dim j As Integer
'create object of excel
ExcelApp = CreateObject("Excel.Application")
ExcelBook = ExcelApp.WorkBooks.Add
ExcelSheet = ExcelBook.WorkSheets(1)
With ExcelSheet
For i = 1 To Me.DataGridView1.RowCount
.cells(i, 1) = Me.DataGridView1.Rows(i - 1).Cells("id").Value
For j = 1 To DataGridView1.Columns.Count - 1
.cells(i, j + 1) = DataGridView1.Rows(i - 1).Cells(j).Value
Next
Next
End With
ExcelApp.Visible = True
'
ExcelSheet = Nothing
ExcelBook = Nothing
ExcelApp = Nothing
End Sub
Once again any help is appreciated, I have looked at different sites but most are not using VB.Net
Here is the error for the first code
Code Error

In 1st Code , you need to try following changes (Header text should not be duplicate in datagridview, It is better to add columnname in your datatable )
'Adding the Columns
For Each column As DataGridViewColumn In DataGridView1.Columns
dt.Columns.Add(column.Name, column.ValueType)
Next
'Adding the Rows
dim dr as datarow
For Each row As DataGridViewRow In DataGridView1.Rows
dr = dt.Newrow
For Each cell As DataGridViewCell In row.Cells
If not isnothing(cell.value) then
dr(datagridview1.columns(cell.ColumnIndex).Name)= cell.Value
End if
Next
dt.rows.add (dr)
Next

In 2nd code you miss to add headers and also while your try to get column values you started your j iterator with 1 so value at 1st column will be missing (if your id column is not a 1st column)
Private Sub ExportToExcel()
Dim ExcelApp As Object, ExcelBook As Object
Dim ExcelSheet As Object
Dim i As Integer
Dim j As Integer
'create object of excel
ExcelApp = CreateObject("Excel.Application")
ExcelBook = ExcelApp.WorkBooks.Add
ExcelSheet = ExcelBook.WorkSheets(1)
dim rowIndex as integer = 1
dim colIndex as integer = 2
''For Headers
With ExcelSheet
For each column as datagridviewcolumn in Me.DataGridView1.columns
if column.name = "Id" then
.cells(rowindex, 1) = Column.HeaderText
else
.cells(rowindex, colIndex) = Column.HeaderText
colIndex = ColIndex + 1
end if
Next
End With
With ExcelSheet
For i = 0 To Me.DataGridView1.RowCount-1
if not isnothing (Me.DataGridView1.Rows(i).Cells(0).value) then
rowindex = rowIndex + 1
ColumnIndex = 2
For j = 0 To DataGridView1.Columns.Count - 1
if datagridview1.columns(j).name = "Id" then
.cells(rowindex, 1) = DataGridView1.Rows(i).Cells(j).Value
else
.cells(rowindex, columnIndex ) = DataGridView1.Rows(i).Cells(j).Value
ColumnIndex = ColumnIndex + 1
End if
Next
End if
Next
End With
ExcelApp.Visible = True
'
ExcelSheet = Nothing
ExcelBook = Nothing
ExcelApp = Nothing
End Sub

I went with the 2nd code. I tried to use your code and it didnt work at first but then I noticed you had named the column index as ColumnIndex, and it was actually needed to be names colIndex, Thanks for all your help.
Here is the finished code,
Private Sub ExportToExcel()
Dim ExcelApp As Object, ExcelBook As Object
Dim ExcelSheet As Object
Dim i As Integer
Dim j As Integer
'create object of excel
ExcelApp = CreateObject("Excel.Application")
ExcelBook = ExcelApp.WorkBooks.Add
ExcelSheet = ExcelBook.WorkSheets(1)
Dim rowIndex As Integer = 1
Dim colIndex As Integer = 1
''For Headers
With ExcelSheet
For Each column As DataGridViewColumn In Me.DataGridView1.Columns
If column.Name = "Id" Then
.cells(rowIndex, 1) = column.HeaderText
Else
.cells(rowIndex, colIndex) = column.HeaderText
colIndex = colIndex + 1
End If
Next
End With
''For Rows
With ExcelSheet
For i = 0 To Me.DataGridView1.RowCount - 1
If Not IsNothing(Me.DataGridView1.Rows(i).Cells(0).Value) Then
rowIndex = rowIndex + 1
colIndex = 1
For j = 0 To DataGridView1.Columns.Count - 1
If DataGridView1.Columns(j).Name = "Id" Then
.cells(rowIndex, 1) = DataGridView1.Rows(i).Cells(j).Value
Else
.cells(rowIndex, colIndex) = DataGridView1.Rows(i).Cells(j).Value
colIndex = colIndex + 1
End If
Next
End If
Next
End With
ExcelApp.Visible = True
'
ExcelSheet = Nothing
ExcelBook = Nothing
ExcelApp = Nothing
End Sub
```

Related

how to remove cell value in the cell offset if a new value with the same data repeated after that?

I want to make a loop in range to zero the offset cell if the cell data is repeated next as below:
Column A Column B
T10 5
T20 10
T10 15
You see I have T10 Repeated maybe after one or many rows, What I want is to use only the last value for T10 (Which is 15 in this example) and make 5 = 0
I use this code in vb.net
Private Sub AdjustTotalStoreWeightPerDiamater()
wb = Workbook Path ...
ws = Worksheet Name ...
lr = last row
Rng = Column Range
Cel = Column Range
i = integer
With ws
lr = .Range("A" & .Rows.Count).End(Excel.XlDirection.xlUp).Row
Rng = ws.Range("A2", "A" & lr)
End With
For i = 2 To lr
For Each Cel In Rng.Cells
If Cel.Value = Cel.Offset(-1, 0).Value Then
Cel.Offset(0, 3).Value = 0
End If
Next
Next
End Sub
But the code does not sense that T10 = T10 to make the change.
Appreciate your support.
I used OleDb to get the data from Excel as a DataTable. Note that I used Extended Properties=""Excel 12.0;HDR=YES;""" at the end of the connection string so we would get the column headers.
Private Function GetExcelData() As System.Data.DataTable
Dim dt As New System.Data.DataTable
Dim ConStr = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\xxxx\Documents\Code\TestCode3\TestCode3\bin\Debug\TestCode1.xlsx;Extended Properties=""Excel 12.0;HDR=YES;"""
Dim SheetName = "Sheet1$"
Using cn = New OleDb.OleDbConnection(ConStr)
Using cmd As New OleDbCommand($"Select * From [{SheetName}];", cn)
cn.Open()
Using dr As OleDbDataReader = cmd.ExecuteReader
dt.Load(dr)
End Using
End Using
End Using
Return dt
End Function
To save the data back to the same excel sheet I used office automation.
Private Sub SaveDataTableToExcel(dt As System.Data.DataTable, RowToStartAt As Integer)
Dim FileToOpen = "C:\Users\xxxx\Documents\Code\TestCode3\TestCode3\bin\Debug\TestCode1.xlsx"
Dim xl As New Excel.Application
Dim wb = DirectCast(xl.Workbooks.Open(FileToOpen), Workbook)
Dim ws = DirectCast(wb.Worksheets(1), Excel.Worksheet)
'Add Headers
For ColumnIndex = 1 To dt.Columns.Count
ws.Cells(RowToStartAt, ColumnIndex) = dt.Columns(ColumnIndex - 1).Caption
Next
'Write data to Excel
For dtRow = 0 To dt.Rows.Count - 1
RowToStartAt += 1
Dim xlColumnIndex = 1
For Each dtcolumn As DataColumn In dt.Columns
ws.Cells(RowToStartAt, xlColumnIndex) = dt(dtRow)(dtcolumn)
xlColumnIndex += 1
Next
Next
wb.Save()
wb.Close()
xl.Quit()
End Sub
The magic happens in happens in the Linq query where we group by Column A and select the Max from Column B. Then it is a simple loop through the returned enumerable to fill a new DataTable that is passed to Excel for saving.
Private Sub OPCode()
Dim dt = GetExcelData()
Dim e = From row In dt.AsEnumerable
Group By TValue = row.Field(Of String)("Column A")
Into Ts = Group, Max(row.Field(Of Double)("Column B"))
Select TValue, Max
Dim Newdt = dt.Clone 'Copies structure but not data
For Each row In e
Newdt.Rows.Add({row.TValue, row.Max})
Next
DataGridView1.DataSource = Newdt 'Just checking if we got the expected data
Dim WhereToAdd = dt.Rows.Count + 3 'Two rows down from original data
SaveDataTableToExcel(Newdt, WhereToAdd)
MessageBox.Show("Done")
End Sub

transfer listbox values to particular rows and column to new workbook

i am writing a code to transfer list box data to new excel workbook. it is working by populating new worksheet from row 2 and particular column. what i want is, list should be populating from row 23 in particular column. i have tried to search but unable to make it work. my code is as below,
Private Sub cmdprint_Click()
Dim xl As New Excel.Application
Dim xlwbook As Excel.Workbook
Dim xlsheet As Excel.Worksheet
xl.DisplayAlerts = False
Set xlwbook = xl.Workbooks.Open("C:\Users\filename.xlsm")
Set xlsheet = xlwbook.Sheets.Item("output")
Dim i As Long, j As Long
j = 2
With UserForm1.lstdatabase1
For i = 0 To UserForm1.lstdatabase1.ListCount - 1
With xlsheet
.Cells(j, 7).End(xlUp).Offset(1).Value = UserForm1.lstdatabase1.List(i, 1) 'column 1
.Cells(j, 8).End(xlUp).Offset(1).Value = UserForm1.lstdatabase1.List(i, 2) 'column 2
j = j + 1
End With
xlwbook.SaveAs ("C:\Users\File name (i want this to be value from userform text box")
xl.DisplayAlerts = True
'no need to carry on searching
Next i
End With
End Sub
Also, i would like to save file save as Textbox value from form, instead of fix name.
can you pl help me with that.
thanks
Try
Private Sub cmdprint_Click()
Dim xl As New Excel.Application
Dim xlwbook As Excel.Workbook
Dim xlsheet As Excel.Worksheet
xl.DisplayAlerts = False
Set xlwbook = xl.Workbooks.Open("C:\Users\filename.xlsm")
Set xlsheet = xlwbook.Sheets.Item("output")
Dim i As Long , j As Long
j = 23
With UserForm1.lstdatabase1
For i = 0 To UserForm1.lstdatabase1.ListCount - 1
With xlsheet
.Cells(j, 7).Value = UserForm1.lstdatabase1.List(i, 1) 'column 1
.Cells(j, 8).Value = UserForm1.lstdatabase1.List(i, 2) 'column 2
j = j + 1
End With
xlwbook.SaveAs ("C:\Users\File name (i want this to be value from userform text box")
xl.DisplayAlerts = True
'no need to carry on searching
Next i
End With

Visual Basic Running QBFC13Lib, SDK, Running GeneralSummaryReportQuery, on Response, can't get the column names as text

I'm using Visual Basic to export a General Summary Report To excel using Quickbooks SDK QBFC13Lib.
On the response, I can't get the column titles. I need the column titles as text to send to an excel cell.
The code for the column titles is at 'Get value of NumColTitleRows
I have a text box MsgBox(ColTitle.value) that I was trying to show the column titles so I could see I was getting them.
enter code here
Public Sub WalkReportRet(ReportRet As IReportRet)
If (ReportRet Is Nothing) Then
Exit Sub
End If
'Go through all the elements of IReportRet
'Get value of ReportTitle
Dim ReportTitle10687 As String
ReportTitle10687 = ReportRet.ReportTitle.GetValue()
'Get value of ReportSubtitle
Dim ReportSubtitle10688 As String
ReportSubtitle10688 = ReportRet.ReportSubtitle.GetValue()
'Get value of NumRows
Dim NumRows10690 As Integer
NumRows10690 = ReportRet.NumRows.GetValue()
'Get value of NumColumns
Dim NumColumns10691 As Integer
NumColumns10691 = ReportRet.NumColumns.GetValue()
'SEND TO EXCEL
Dim appXL As Excel.Application
Dim wbXl As Excel.Workbook
Dim shXL As Excel.Worksheet
Dim raXL As Excel.Range
' Start Excel and get Application object.
appXL = CreateObject("Excel.Application")
appXL.Visible = True
' Add a new workbook.
wbXl = appXL.Workbooks.Add
shXL = wbXl.ActiveSheet
'Create an array to set multiple values at once.
Dim qbdata(200, 10) As String
qbdata(0, 0) = ReportTitle10687
qbdata(0, 1) = ReportSubtitle10688
qbdata(0, 2) = NumRows10690.ToString
qbdata(0, 3) = NumColumns10691.ToString
'Get value of NumColTitleRows
Dim NumColTitleRows10692 As Integer
NumColTitleRows10692 = ReportRet.NumColTitleRows.GetValue()
If (Not ReportRet.ColDescList Is Nothing) Then
Dim i10693 As Integer
For i10693 = 0 To ReportRet.ColDescList.Count - 1
Dim ColDesc As IColDesc
ColDesc = ReportRet.ColDescList.GetAt(i10693)
If (Not ColDesc.ColTitleList Is Nothing) Then
Dim i10694 As Integer
For i10694 = 0 To ColDesc.ColTitleList.Count - 1
Dim ColTitle As IColTitle
ColTitle = ColDesc.ColTitleList.GetAt(i10694)
MsgBox(ColTitle.value)
Next i10694
End If
'Get value of ColType
Dim ColType10695 As ENColType
ColType10695 = ColDesc.ColType.GetValue()
Next i10693
End If
If (Not ReportRet.ReportData Is Nothing) Then
If (Not ReportRet.ReportData.ORReportDataList Is Nothing) Then
Dim i10696 As Integer
'this runs the rows
For i10696 = 0 To ReportRet.ReportData.ORReportDataList.Count - 1
Dim ORReportData10697 As IORReportData
ORReportData10697 = ReportRet.ReportData.ORReportDataList.GetAt(i10696)
If (Not ORReportData10697.DataRow Is Nothing) Then
If (Not ORReportData10697.DataRow Is Nothing) Then
If (Not ORReportData10697.DataRow.RowData Is Nothing) Then
End If
If (Not ORReportData10697.DataRow.ColDataList Is Nothing) Then
Dim i10698 As Integer
For i10698 = 0 To ORReportData10697.DataRow.ColDataList.Count - 1
Dim ColData As IColData
ColData = ORReportData10697.DataRow.ColDataList.GetAt(i10698)
qbdata(i10696 + 5, i10698) = ColData.value.GetValue.ToString
Next i10698
End If
End If
End If
If (Not ORReportData10697.TextRow Is Nothing) Then
If (Not ORReportData10697.TextRow Is Nothing) Then
qbdata(i10696 + 5, 0) = ORReportData10697.TextRow.value.GetValue.ToString
End If
End If
If (Not ORReportData10697.SubtotalRow Is Nothing) Then
If (Not ORReportData10697.SubtotalRow Is Nothing) Then
If (Not ORReportData10697.SubtotalRow.RowData Is Nothing) Then
End If
If (Not ORReportData10697.SubtotalRow.ColDataList Is Nothing) Then
Dim i10699 As Integer
For i10699 = 0 To ORReportData10697.SubtotalRow.ColDataList.Count - 1
Dim ColData As IColData
ColData = ORReportData10697.SubtotalRow.ColDataList.GetAt(i10699)
qbdata(i10696 + 5, i10699) = ColData.value.GetValue.ToString
Next i10699
End If
End If
End If
If (Not ORReportData10697.TotalRow Is Nothing) Then
If (Not ORReportData10697.TotalRow Is Nothing) Then
If (Not ORReportData10697.TotalRow.RowData Is Nothing) Then
End If
If (Not ORReportData10697.TotalRow.ColDataList Is Nothing) Then
Dim i10700 As Integer
For i10700 = 0 To ORReportData10697.TotalRow.ColDataList.Count - 1
Dim ColData As IColData
ColData = ORReportData10697.TotalRow.ColDataList.GetAt(i10700)
qbdata(i10696 + 5, i10700) = ColData.value.GetValue.ToString
Next i10700
End If
End If
End If
Next i10696
End If
End If
' Fill A2:B6 with an array of data
shXL.Range("A1", "K205").Value = qbdata
' Make sure Excel is visible and give the user control
' of Excel's lifetime.
appXL.Visible = True
appXL.UserControl = True
' Release object references.
raXL = Nothing
shXL = Nothing
wbXl = Nothing
appXL.Quit()
appXL = Nothing
End Sub
Got it! I had a null on the first item in the list, and wasn't handling it
enter code here
If (Not ReportRet.ColDescList Is Nothing) Then
Dim i10693 As Integer
For i10693 = 0 To ReportRet.ColDescList.Count - 1
Dim ColDesc As IColDesc
ColDesc = ReportRet.ColDescList.GetAt(i10693)
If (Not ColDesc.ColTitleList Is Nothing) Then
Dim i10694 As Integer
For i10694 = 0 To ColDesc.ColTitleList.Count - 1
Dim ColTitle As IColTitle
ColTitle = ColDesc.ColTitleList.GetAt(i10694)
If (Not ColTitle.value Is Nothing) Then
qbdata(i10694 + 2, i10693) = ColTitle.value.GetValue.ToString
End If
Next i10694
End If
Dim ColType10695 As ENColType
ColType10695 = ColDesc.ColType.GetValue()
Next i10693
End If
For reference, this should be universal code for visual studio visual basic to export a balance sheet previous year comparison from open company file into excel. A few small changes would change it to export a P&L. This code only supports up to 200 lines, it would have to be modified for a longer report. (the array expanded and the range in excel expanded).
example of Quickbooks report exported to excel
enter code here Private Sub RunChurchCashFlowReportToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles RunChurchCashFlowReportToolStripMenuItem.Click
DoGeneralSummaryReportBalanceSheetQuery()
DoGeneralSummaryReportProfitAndLossQuery()
' RunCustomSummaryReport()
End Sub
Public Sub DoGeneralSummaryReportBalanceSheetQuery()
Dim sessionBegun As Boolean
sessionBegun = False
Dim connectionOpen As Boolean
connectionOpen = False
Dim sessionManager As QBSessionManager
sessionManager = Nothing
Try
'Create the session Manager object
sessionManager = New QBSessionManager
'Create the message set request object to hold our request
Dim requestMsgSet As IMsgSetRequest
requestMsgSet = sessionManager.CreateMsgSetRequest("US", 13, 0)
requestMsgSet.Attributes.OnError = ENRqOnError.roeContinue
BuildGeneralSummaryReportBalanceSheetQueryRq(requestMsgSet)
'Connect to QuickBooks and begin a session
sessionManager.OpenConnection("", "ChurchReports")
connectionOpen = True
sessionManager.BeginSession("", ENOpenMode.omDontCare)
sessionBegun = True
'Send the request and get the response from QuickBooks
Dim responseMsgSet As IMsgSetResponse
responseMsgSet = sessionManager.DoRequests(requestMsgSet)
'End the session and close the connection to QuickBooks
sessionManager.EndSession()
sessionBegun = False
sessionManager.CloseConnection()
connectionOpen = False
WalkGeneralSummaryReportQueryRs(responseMsgSet)
Catch e As Exception
MessageBox.Show(e.Message, "Error")
If (sessionBegun) Then
sessionManager.EndSession()
End If
If (connectionOpen) Then
sessionManager.CloseConnection()
End If
End Try
End Sub
Public Sub WalkGeneralSummaryReportQueryRs(responseMsgSet As IMsgSetResponse)
If (responseMsgSet Is Nothing) Then
Exit Sub
End If
Dim responseList As IResponseList
responseList = responseMsgSet.ResponseList
If (responseList Is Nothing) Then
Exit Sub
End If
'if we sent only one request, there is only one response, we'll walk the list for this sample
For j = 0 To responseList.Count - 1
Dim response As IResponse
response = responseList.GetAt(j)
'check the status code of the response, 0=ok, >0 is warning
If (response.StatusCode >= 0) Then
'the request-specific response is in the details, make sure we have some
If (Not response.Detail Is Nothing) Then
'make sure the response is the type we're expecting
Dim responseType As ENResponseType
responseType = CType(response.Type.GetValue(), ENResponseType)
If (responseType = ENResponseType.rtGeneralSummaryReportQueryRs) Then
'upcast to more specific type here, this is safe because we checked with response.Type check above
Dim ReportRet As IReportRet
ReportRet = CType(response.Detail, IReportRet)
WalkReportRet(ReportRet)
End If
End If
End If
Next j
End Sub
Public Sub WalkReportRet(ReportRet As IReportRet)
If (ReportRet Is Nothing) Then
Exit Sub
End If
'Go through all the elements of IReportRet
'Get value of ReportTitle
Dim ReportTitle10687 As String
ReportTitle10687 = ReportRet.ReportTitle.GetValue()
'Get value of ReportSubtitle
Dim ReportSubtitle10688 As String
ReportSubtitle10688 = ReportRet.ReportSubtitle.GetValue()
'Get value of NumRows
Dim NumRows10690 As Integer
NumRows10690 = ReportRet.NumRows.GetValue()
'Get value of NumColumns
Dim NumColumns10691 As Integer
NumColumns10691 = ReportRet.NumColumns.GetValue()
'SEND TO EXCEL
Dim appXL As Excel.Application
Dim wbXl As Excel.Workbook
Dim shXL As Excel.Worksheet
Dim raXL As Excel.Range
' Start Excel and get Application object.
appXL = CreateObject("Excel.Application")
appXL.Visible = True
' Add a new workbook.
wbXl = appXL.Workbooks.Add
shXL = wbXl.ActiveSheet
'Create an array to set multiple values at once.
Dim qbdata(200, 10) As String
qbdata(0, 0) = ReportTitle10687
qbdata(0, 1) = ReportSubtitle10688
qbdata(0, 2) = NumRows10690.ToString
qbdata(0, 3) = NumColumns10691.ToString
'Get value of NumColTitleRows
Dim NumColTitleRows10692 As Integer
NumColTitleRows10692 = ReportRet.NumColTitleRows.GetValue()
If (Not ReportRet.ColDescList Is Nothing) Then
Dim i10693 As Integer
For i10693 = 0 To ReportRet.ColDescList.Count - 1
Dim ColDesc As IColDesc
ColDesc = ReportRet.ColDescList.GetAt(i10693)
If (Not ColDesc.ColTitleList Is Nothing) Then
Dim i10694 As Integer
For i10694 = 0 To ColDesc.ColTitleList.Count - 1
Dim ColTitle As IColTitle
ColTitle = ColDesc.ColTitleList.GetAt(i10694)
If (Not ColTitle.value Is Nothing) Then
qbdata(i10694 + 2, i10693) = ColTitle.value.GetValue.ToString
End If
Next i10694
End If
Dim ColType10695 As ENColType
ColType10695 = ColDesc.ColType.GetValue()
Next i10693
End If
If (Not ReportRet.ReportData Is Nothing) Then
If (Not ReportRet.ReportData.ORReportDataList Is Nothing) Then
Dim i10696 As Integer
'this runs the rows
For i10696 = 0 To ReportRet.ReportData.ORReportDataList.Count - 1
Dim ORReportData10697 As IORReportData
ORReportData10697 = ReportRet.ReportData.ORReportDataList.GetAt(i10696)
If (Not ORReportData10697.DataRow Is Nothing) Then
If (Not ORReportData10697.DataRow Is Nothing) Then
If (Not ORReportData10697.DataRow.RowData Is Nothing) Then
End If
If (Not ORReportData10697.DataRow.ColDataList Is Nothing) Then
Dim i10698 As Integer
For i10698 = 0 To ORReportData10697.DataRow.ColDataList.Count - 1
Dim ColData As IColData
ColData = ORReportData10697.DataRow.ColDataList.GetAt(i10698)
qbdata(i10696 + 5, i10698) = ColData.value.GetValue.ToString
Next i10698
End If
End If
End If
If (Not ORReportData10697.TextRow Is Nothing) Then
If (Not ORReportData10697.TextRow Is Nothing) Then
qbdata(i10696 + 5, 0) = ORReportData10697.TextRow.value.GetValue.ToString
End If
End If
If (Not ORReportData10697.SubtotalRow Is Nothing) Then
If (Not ORReportData10697.SubtotalRow Is Nothing) Then
If (Not ORReportData10697.SubtotalRow.RowData Is Nothing) Then
End If
If (Not ORReportData10697.SubtotalRow.ColDataList Is Nothing) Then
Dim i10699 As Integer
For i10699 = 0 To ORReportData10697.SubtotalRow.ColDataList.Count - 1
Dim ColData As IColData
ColData = ORReportData10697.SubtotalRow.ColDataList.GetAt(i10699)
qbdata(i10696 + 5, i10699) = ColData.value.GetValue.ToString
Next i10699
End If
End If
End If
If (Not ORReportData10697.TotalRow Is Nothing) Then
If (Not ORReportData10697.TotalRow Is Nothing) Then
If (Not ORReportData10697.TotalRow.RowData Is Nothing) Then
End If
If (Not ORReportData10697.TotalRow.ColDataList Is Nothing) Then
Dim i10700 As Integer
For i10700 = 0 To ORReportData10697.TotalRow.ColDataList.Count - 1
Dim ColData As IColData
ColData = ORReportData10697.TotalRow.ColDataList.GetAt(i10700)
qbdata(i10696 + 5, i10700) = ColData.value.GetValue.ToString
Next i10700
End If
End If
End If
Next i10696
End If
End If
' Fill A2:B6 with an array of data
shXL.Range("A1", "K205").Value = qbdata
' Make sure Excel is visible and give the user control
' of Excel's lifetime.
appXL.Visible = True
appXL.UserControl = True
' Release object references.
raXL = Nothing
shXL = Nothing
wbXl = Nothing
appXL.Quit()
appXL = Nothing
End Sub
Public Sub BuildGeneralSummaryReportBalanceSheetQueryRq(requestMsgSet As IMsgSetRequest)
Dim GeneralSummaryReportQueryRq As IGeneralSummaryReportQuery
GeneralSummaryReportQueryRq = requestMsgSet.AppendGeneralSummaryReportQueryRq()
'Set field value for GeneralSummaryReportType
GeneralSummaryReportQueryRq.GeneralSummaryReportType.SetValue(ENGeneralSummaryReportType.gsrtBalanceSheetPrevYearComp)
'Set field value for DisplayReport
GeneralSummaryReportQueryRq.DisplayReport.SetValue(True)
'set report period
GeneralSummaryReportQueryRq.ORReportPeriod.ReportDateMacro.SetValue(ENReportDateMacro.rdmLastYear)
'Set field value for ReportDetailLevelFilter
GeneralSummaryReportQueryRq.ReportDetailLevelFilter.SetValue(ENReportDetailLevelFilter.rdlfAll)
'Set field value for ReportPostingStatusFilter
GeneralSummaryReportQueryRq.ReportPostingStatusFilter.SetValue(ENReportPostingStatusFilter.rpsfEither)
'Set field value for SummarizeColumnsBy
GeneralSummaryReportQueryRq.SummarizeColumnsBy.SetValue(ENSummarizeColumnsBy.scbTotalOnly)
'Set field value for IncludeSubcolumns
GeneralSummaryReportQueryRq.IncludeSubcolumns.SetValue(False)
'Set field value for ReportCalendar
GeneralSummaryReportQueryRq.ReportCalendar.SetValue(ENReportCalendar.rcFiscalYear)
'Set field value for ReturnRows
GeneralSummaryReportQueryRq.ReturnRows.SetValue(ENReturnRows.rrAll)
'Set field value for ReturnColumns
GeneralSummaryReportQueryRq.ReturnColumns.SetValue(ENReturnColumns.rcAll)
'Set field value for ReportBasis
GeneralSummaryReportQueryRq.ReportBasis.SetValue(ENReportBasis.rbCash)
End Sub

Matching subset of data

I am populating ActiveX control labels with a subset of Excel data in VBA. My code previously worked for the entire Excel workbook, but once I changed my code to only reference a subset of the data, the incorrect data is being entered.
Here is a snapshot of example data. In my code, Column 6= CY and Column 7 = FY. The code is currently populating my labels with the headers of Column 6 and 7 rather than the values of 'active' or 'merged' projects.
As mentioned, I am not receiving any error messages, but the correct data is not being added to my ActiveX labels. FYI... In line 31 Code1 is the name of an ActiveX label.
Private Sub CommandButton1_Click()
Dim objExcel As Excel.Application
Dim exWB As Excel.Workbook
Dim rng As Excel.Range, m, rw As Excel.Range
Dim num, TableNo, seq As Integer
Dim ctl As MSForms.Label
Dim ils As Word.InlineShape
Dim rngrow As Excel.Range
Dim active As Excel.Range
Set objExcel = New Excel.Application
TableNo = ActiveDocument.Tables.Count
num = 3
seq = 1
Set exWB = objExcel.Workbooks.Open("O:\Documents\"Database.csv")
Set rng = exWB.Sheets("Sheet1").Cells
''''Select active projects as subset
For Each rngrow In rng.Range("A1:L144")
If rngrow.Columns(8).value = "Active" Or rngrow.Columns(8).value = "Merged" Then
If active Is Nothing Then
Set active = rngrow
Else
Set active = Union(active, rngrow)
End If
End If
Next rngrow
m = objExcel.Match(ActiveDocument.Code1.Caption, active.Columns(3), 0)
'' Now, create all ActiveX FY labels and populate with FY Use
Do
Set ils = ActiveDocument.Tables(num).cell(6, 2).Range.InlineShapes.AddOLEControl(ClassType:="Forms.Label.1")
Set ctl = ils.OLEFormat.Object
ctl.Name = "FY" & seq
If Not IsError(m) Then
Set rw = rng.Rows(m)
ctl.Caption = rw.Cells(7).value
Else
MsgBox "No match found"
End If
seq = seq + 1
num = num + 1
Loop Until num = TableNo + 1
'' Now, create all ActiveX CY labels and populate with CY
num = 3
seq = 1
Do
Set ils = ActiveDocument.Tables(num).cell(7, 2).Range.InlineShapes.AddOLEControl(ClassType:="Forms.Label.1")
Set ctl = ils.OLEFormat.Object
ctl.Name = "CY" & seq
If Not IsError(m) Then
Set rw = rng.Rows(m)
ctl.Caption = rw.Cells(6).value
Else
MsgBox "No match found"
End If
seq = seq + 1
num = num + 1
Loop Until num = TableNo + 1
Set exWB = Nothing
End Sub
Link to my previous question below:
Using Excel data to create Word Doc caption labels in VBA
This:
For Each rngrow In rng.Range("A1:L144")
will be interpreted as
For Each rngrow In rng.Range("A1:L144").Cells
so your loop will be A1, B1, C1, ... L1 then A2, B2 etc.
It seems like you meant it to be:
For Each rngrow In rng.Range("A1:L144").Rows
so rngRow will be A1:L1, then A2:L2, etc.
EDIT - You can't refer to active using something like MsgBox(active.Range ("A2")), since it's a multi-area range.
Try this for example -
For Each rw in active.Rows
debug.print "Row:" & rw.Row, rw.cells(8).value
Next rw
EDIT2: try this instead. Untested but I think it should work OK
Private Sub CommandButton1_Click()
Dim objExcel As Excel.Application
Dim exWB As Excel.Workbook
Dim data, r As Long, resRow As Long, seq As Long, num As Long
Dim doc As Document
'get the Excel data as a 2D array
Set objExcel = New Excel.Application
Set exWB = objExcel.Workbooks.Open("O:\Documents\Database.csv")
data = exWB.Sheets("Sheet1").Range("A1:L144").Value '>> 2D array
exWB.Close False
objExcel.Quit
resRow = 0
'find the first matching row, if any
For r = 1 To UBound(data, 1)
If (data(r, 8) = "Active" Or data(r, 8) = "Merged") And _
data(r, 3) = doc.Code1.Caption Then
resRow = r 'this is the row we want
Exit Sub 'done looking
End If
Next r
Set doc = ActiveDocument
seq = 1
For num = 3 To doc.Tables.Count
With doc.Tables(num)
AddLabel .Cell(6, 2), "FY" & seq, IIf(resRow > 0, data(resRow, 7), "Not found")
AddLabel .Cell(7, 2), "CY" & seq, IIf(resRow > 0, data(resRow, 6), "Not found")
End With
seq = seq + 1
Next num
End Sub
'add a label to a cell, set its name and caption
Sub AddLabel(theCell As Cell, theName As String, theCaption As String)
Dim ils As InlineShape, ctl As MSForms.Label
Set ils = theCell.Range.InlineShapes.AddOLEControl(ClassType:="Forms.Label.1")
Set ctl = ils.OLEFormat.Object
ctl.Name = theName
ctl.Caption = theCaption
End Sub

Unique rows in Listview (Userform) VBA

I have a table in excel and I want to have the records displayed in a userform using the listview control. The challange I'm facing is that I only want 5 columns to be displayed and only unique rows.
The code I have so far is as follows:
Private Sub LoadListView()
Dim wksSource As Worksheet
Dim rngData, rngCell As Range
Dim LstItem As ListItem
Dim RowCount, ColCount, i, j As Long
Dim CountryCol, ShippingWay, SortCode, FirstException, LastException, Performance_OK_NOK, Container,
CountSimilar, a As Integer
Set wksSource = Worksheets("Sheet3")
Set rngData = wksSource.Range("A1").CurrentRegion
Me.ListView1.ColumnHeaders.Add Text:="RowNr", Width:=70
For Each rngCell In rngData.Rows(1).Cells
If rngCell = "service_def_code" Or rngCell = "package_sort" Or rngCell = "ship_to_country_id" Or
rngCell = "first_tracking_exception_message" _
Or rngCell = "last_tracking_exception_message" Then
Me.ListView1.ColumnHeaders.Add Text:=rngCell.Value, Width:=80
End If
Next rngCell
RowCount = rngData.Rows.Count
ColCount = rngData.Columns.Count
For i = 1 To ColCount
If wksSource.Cells(1, i) = "ship_to_country_id" Then
CountryCol = i
ElseIf wksSource.Cells(1, i) = "service_def_code" Then
ShippingWay = i
ElseIf wksSource.Cells(1, i) = "package_sort" Then
SortCode = i
ElseIf wksSource.Cells(1, i) = "first_tracking_exception_message" Then
FirstException = i
ElseIf wksSource.Cells(1, i) = "last_tracking_exception_message" Then
LastException = i
ElseIf wksSource.Cells(1, i) = "performance_result" Then
Performance_OK_NOK = i
End If
Next i
j = 1
For i = 2 To RowCount
If wksSource.Cells(i, Performance_OK_NOK) = "NOK" then
Set LstItem = Me.ListView1.ListItems.Add(Text:=j)
LstItem.ListSubItems.Add Text:=rngData(i, CountryCol)
LstItem.ListSubItems.Add Text:=rngData(i, ShippingWay)
LstItem.ListSubItems.Add Text:=rngData(i, SortCode)
LstItem.ListSubItems.Add Text:=rngData(i, FirstException)
LstItem.ListSubItems.Add Text:=rngData(i, LastException)
j = j + 1
end if
next i
end sub
So what I want to do is to have only unique rows displayed and the subitems represents a row. I checked and searched for a solution, but couldn't find one which I understand. Can someone please help?
you can use a dictionary. For each row create a key with the values of the five columns. if it is not in the dictionary, add it to the dictionary, add it to the listview.
The below example creates a key from columns a, b. Adapt it so you create your key based on your five columns. below i only get "b2" once even though it appears twice in table(cols a,b)
Public Sub sAddToList()
'REQUIRES MICROSOFT SCRIPTING RUNTIME LIB, (Add using Tools->References from the VB menu)
Dim d As Dictionary
Dim rowKey As String
Dim i As Integer
Set d = New Dictionary
For i = 1 To 4
rowKey = CStr(Sheet1.Cells(i, 1).Value) + CStr(Sheet1.Cells(i, 2).Value)
If Not d.Exists(rowKey) Then
d.Add rowKey, rowKey
'add to your list view
End If
Next
End Sub
IF YOUR EXCEL SUPPORTS the UNIQUE function then there is no need for VBA.

Resources