Problem in excel report generation - vb.net

I am working on an Excel report and I would like the top rows to be empty to allow for an image to be inserted. However, I do not want the image size to change the width of the columns and would rather the data below do that.
This is what I have so far:
If ComDset.Tables(0).Rows.Count > 0 Then
Try
With Excel
.SheetsInNewWorkbook = 1
.Workbooks.Add()
.Worksheets(1).Select()
Dim i As Integer = 1
For col = 0 To ComDset.Tables(0).Columns.Count - 1
.cells(1, i).value = ComDset.Tables(0).Columns(col).ColumnName
.cells(1, i).EntireRow.Font.Bold = True
i += 1
Next
i = 2
Dim k As Integer = 1
For col = 0 To ComDset.Tables(0).Columns.Count - 1
i = 2
For row = 0 To ComDset.Tables(0).Rows.Count - 1
.Cells(i, k).Value = ComDset.Tables(0).Rows(row).ItemArray(col)
i += 1
Next
k += 1
Next
filename = "ShiftReport" & Format(MdbDate, "dd-MM-yyyy") & ".xls"
.ActiveCell.Worksheet.SaveAs(filename)
End With
System.Runtime.InteropServices.Marshal.ReleaseComObject(Excel)
Excel = Nothing
Catch ex As Exception
MsgBox(ex.Message)
End Try
' The excel is created and opened for insert value. We most close this excel using this system
Dim pro() As Process = System.Diagnostics.Process.GetProcessesByName("EXCEL")
For Each i As Process In pro
i.Kill()
Next
End If

I would recommend trying to "merge" the cells in the top 2 rows. You could take A1 through say K2 and merge them and the image would fit just fine in there...
Range("A1:K2").Select
Selection.Merge

One way to create your report with the image included is to create a template workbook (.xlt file) in which you have already set up your required formatting and image(s). Then in your code, create the new report workbook from the template like this:
.Workbooks.Add("path\to\report_template.xlt")
To make your image fixed in size and independent of column widths, right-click on it, choose "Format Picture...", open the Properties tab and within Object Positioning select "Don't move or size with cells".
Alternatively, use code to add the picture to a blank workbook as follows:
ActiveSheet.Pictures.Insert( "path\to\image.jpg" ).Select
With Selection
.Placement = xlFreeFloating
.PrintObject = True
End With
You could control the first row to be used to output your data by initialising a row variable to an appropriate value.
You can also fit the column sizes to match your data by using the AutoFit method.
Your code might then look like this:
Try
With Excel
.SheetsInNewWorkbook = 1
.Workbooks.Add("path\to\report_template.xlt")
.Worksheets(1).Select()
Dim outputRow As Integer = 8
For col = 0 To ComDset.Tables(0).Columns.Count - 1
.Cells(outputRow, col+1).value = ComDset.Tables(0).Columns(col).ColumnName
.Cells(outputRow, col+1).EntireRow.Font.Bold = True
Next
outputRow += 1
For y = 0 To ComDset.Tables(0).Rows.Count - 1
For x = 0 To ComDset.Tables(0).Columns.Count - 1
.Cells(outputRow + y, x).Value = ComDset.Tables(0).Rows(y).ItemArray(x)
Next
Next
.Cells(outputRow, 1).CurrentRegion.Columns.AutoFit
filename = "ShiftReport" & Format(MdbDate, "dd-MM-yyyy") & ".xls"
.ActiveCell.Worksheet.SaveAs(filename)
End With
System.Runtime.InteropServices.Marshal.ReleaseComObject(Excel)
Excel = Nothing
Catch ex As Exception
MsgBox(ex.Message)
End Try
Choose a suitable initial value for the outputRow variable to give enough space for your image.

An alternate to consider, if the image is only needed for printed reports, is to put it into the page header.
Worksheets(1).PageSetup.LeftHeaderPicture.Filename = "C:\header.JPG"
The image will be embedded in the file. It will only be visible in 'Print preview' mode and when printing the report.

Related

CopyPicture Range Name after other cell

I'm trying to CopyPicture cells in Column B, and name them the value in Column 1. I have code that works, except it keeps giving the pictures the wrong names. The baffling thing is that sometimes it works perfectly, and other times it does not.
I have tried to cobble together a routine based on posted examples of the CopyPicture command. I'm pasting it in below.
Yes, I'm a newbie at VBScript. Be gentle. ;-)
Sub makepic()
Dim path As String
path = "C:\BP\BP2020\JPGs\"
Dim CLen As Integer
Dim cntr As Integer
cntr = 1
Dim rgExp As Range
Dim CCntr As String
CString2 = "A1:A6"
Set rgExp2 = Range(CString2)
CString = "B1:B6"
Set rgExp = Range(CString)
For I = 1 To rgExp.Cells.Count Step 1
CCntr = rgExp2.Cells(I).Value
rgExp.Cells.Cells(I).Font.Size = 72
rgExp.Cells.Cells(I).CopyPicture Appearance:=xlScreen, Format:=xlBitmap
rgExp.Cells.Cells(I).Font.Size = 14
''' Create an empty chart with exact size of range copied
CLen = Len(rgExp.Cells.Cells(I).Value)
CWidth = CLen * 85
With ActiveSheet.ChartObjects.Add(Left:=1600, Top:=rgExp.Top, _
Width:=CWidth, Height:=50)
.Name = "ChartVolumeMetricsDevEXPORT"
.Activate
End With
''' Paste into chart area, export to file, delete chart.
If CCntr <> "" Then
ActiveChart.Paste
Selection.Name = "pastedPic"
ActiveSheet.ChartObjects("ChartVolumeMetricsDevEXPORT").Chart.Export (path + CCntr & ".jpg")
ActiveSheet.ChartObjects("ChartVolumeMetricsDevEXPORT").Delete
End If
cntr = cntr + 1
Next
End Sub
Again, I expect -- for example -- a picture of the contents of cell B1 to have the name of the contents of A1. I tried making the range A1:B4 (for example), but that got me 8 pictures. I finally decided to try to make 2 ranges, but that didn't work either.

catia v5 export tree through VBA macro

I need to export the Catia Spec tree to use as a BoM.
The Export Should:
Go to Excel and will use the WalkDownTree function.
Have the PartNumber, Nomenclature and a User Added
Property called "Sinex Ref".
It will also have to make sure that the Exported Tree ignores Parts
and Products called "Ref".
Present the Quantity of each item using the
PartNumber.
Include the deactivated parts but mention that they
are deactivated.
I'm new to Catia and VBA and have come up with the following (I made adjustments to other macros that i have found but noticed that they ignore the children in the Tree). Currently the macro generates the Excel file and in the same cell cycles through all of the parts and children in the spec tree, regardless if they're deactivated or not.
Sub CATMain()
' ********* is the current document a CATIA Product **************
If CATIA.Documents.Count = 0 Then
MsgBox "There are no CATIA documents open. Please open a CATIA document and try again.", ,msgboxtext
Exit Sub
End If
If InStr(CATIA.ActiveDocument.Name, ".CATProduct") < 1 Then
MsgBox "The active document is not a Product. Please open a CATIA Product and try again.", ,msgboxtext
Exit Sub
End If
' ************* General declarations for the Active CATIA session *****************
Dim oProdDoc As ProductDocument
t = 1
Set oProdDoc = CATIA.ActiveDocument
Dim oRootProd As Product
Set oRootProd = oProdDoc.Product
Dim par As Parameters
Set par = oRootProd.UserRefProperties
Dim SinexRef As String
' *************** begin spec tree scroll ******************
Call WalkDownTree(oRootProd)
End Sub
Sub WalkDownTree(oInProduct As Product)
Dim oInstances As Products
Set oInstances = oInProduct.Products
On Error Resume Next
Set Excel = GetObject(, "EXCEL.Application")
If Err.Number <> 0 Then
Set Excel = CreateObject("EXCEL.Application")
Excel.Visible = True
Excel.Workbooks.Add
End If
If t <> 1 Then
for i=1 to oInProduct.Count
'**************************** Export title ***************************
row=2
col=1
Excel.Columns.Columns(1).Columnwidth = 5
Excel.Columns.Columns(2).Columnwidth = 15
Excel.Cells(row,col+1).Value = "CATProduct:"
Excel.Cells(row,col+1).Font.Bold = true
Excel.Cells(row,col+1).HorizontalAlignment = 3
Excel.Cells(row,col+2).Value = CATIA.ActiveDocument.Name
' **************************** Export column titles ***************
row=4
Excel.Cells(row,col+1).Value = "Instance Name"
Excel.Cells(row,col+1).Font.Bold = true
Excel.Columns.Columns(2).Columnwidth = 20
Excel.Cells(row,col+1).borders.LineStyle = 1
Excel.Cells(row,col+1).HorizontalAlignment = 3
Excel.Cells(row+2,col+1).Value = oInProduct.ReferenceProduct.PartNumber
Excel.Cells(row,col+2).Value = "Ref"
Excel.Cells(row,col+2).Font.Bold = true
Excel.Columns.Columns(3).Columnwidth = 15
Excel.Cells(row,col+2).borders.LineStyle = 1
Excel.Cells(row,col+2).HorizontalAlignment = 3
Excel.Cells(row+2,col+2).Value = oInProduct.ReferenceProduct.Nomenclature
Excel.Cells(row,col+3).Value = "Quantity"
Excel.Cells(row,col+3).Font.Bold = true
Excel.Columns.Columns(4).Columnwidth = 15
Excel.Cells(row,col+3).borders.LineStyle = 1
Excel.Cells(row,col+3).HorizontalAlignment = 3
Excel.Cells(row+2,col+3).Value = 1 'insert item quantity corresponding to PartNumber
Excel.Cells(row,col+4).Value = "SinexRef"
Excel.Cells(row,col+4).Font.Bold = true
Excel.Columns.Columns(5).Columnwidth = 15
Excel.Cells(row,col+4).borders.LineStyle = 1
Excel.Cells(row,col+4).HorizontalAlignment = 3
Excel.Cells(row+2,col+4).Value = 1 'insert Sinex Ref corresponding to PartNumber
t = t + 1
Next
End If
Dim k As Integer
For k = 1 To oInstances.Count
Dim oInst As Product
Set oInst = oInstances.Item(k)
Call WalkDownTree(oInst)
Next
End Sub
Assuming by
in the same cell cycles through all of the parts and children in the spec tree
you mean that it is writing/overwriting data from CATIA in the same cell, that is because you aren't incrementing anything regarding Excel rows/columns.
I personally would create headers for things like CATProduct, Instance Name, etc. then put pure data below instead of repeating these identical headers every single time, but your format will work as well, it might just be more difficult to summarize data in Excel.
Anyway, to maintain your existing format, you need to increment your Row at the end of your loop, around where t is incremented.
In the existing loop, it appears that rows 2-6 are used (5 rows total) for the first oInProduct. There is a row = 2 at the beginning of the loop which needs to be put just before the loop, this means it will start from the second row. There is also a row = 4 inside the loop which needs to be changed, we can use row = row + 2 to get the same effect. Then, at the end of the loop, we increment again to reach that total of 5, so use row = row + 3.
row = 2
for i = 1 to oInProduct.Count
'**************************** Export title ***************************
col=1
Excel.Columns.Columns(1).Columnwidth = 5
...
row = row + 2 'previously row = 4
...
Excel.Cells(row,col + 4).HorizontalAlignment = 3
Excel.Cells(row + 2,col + 4).Value = 1 'insert Sinex Ref corresponding to PartNumber
t = t + 1
row = row + 3
Next
Try
-->Analyze-->Bill of Material-->Define Format (for optional options)-->>Save as-->File format as .xls
Or:
-->File--> Save As --> Filetype:txt...Sure it's txt but maybe you can convert to .xls
(expecially if you have missing licenses)
I have used AssemblyConverter object which is available in Catia libraries to extract BOM.I found this when I recorded macro using the steps mentioned in above comment.
Try -->Analyze-->Bill of Material-->Define Format (for optional options)-->>Save as-->File format as .xls
I think this is the simplest and fast. Also, we can change format and location of file too.
Recorded Macro:
Sub CATMain()
Dim productDocument1 As ProductDocument
Set productDocument1 = CATIA.ActiveDocument
Dim product1 As Product
Set product1 = productDocument1.Product
Dim assemblyConvertor1 As AssemblyConvertor
Set assemblyConvertor1 = product1.GetItem("BillOfMaterial")
Dim arrayOfVariantOfBSTR1(4)
arrayOfVariantOfBSTR1(0) = "Quantity"
arrayOfVariantOfBSTR1(1) = "Part Number"
arrayOfVariantOfBSTR1(2) = "Type"
arrayOfVariantOfBSTR1(3) = "Nomenclature"
arrayOfVariantOfBSTR1(4) = "Revision"
Set assemblyConvertor1Variant = assemblyConvertor1
assemblyConvertor1Variant.SetCurrentFormat arrayOfVariantOfBSTR1
Dim arrayOfVariantOfBSTR2(1)
arrayOfVariantOfBSTR2(0) = "Quantity"
arrayOfVariantOfBSTR2(1) = "Part Number"
Set assemblyConvertor1Variant = assemblyConvertor1
assemblyConvertor1Variant.SetSecondaryFormat arrayOfVariantOfBSTR2
assemblyConvertor1.[Print] "XLS", "C:\Users\Desktop\BOM.xls", product1
End Sub

My script to compare two excel files is not working

So I am writing a script to compare two excel files.
I'm using a For loop in the first workbook to get the references I want to find in the second workbook (6450 rows long so that no For loop, way to slow)
I have been looking for some way to use the VLOOKUP thing but i could not make it work Here is the code :
For i = 7 to numLines ''numLines is the number of used lines of the first workbook
If '''test to get out of the LOOP
objExcel.Workbooks(Str1).Sheets(1).Range("D"&i)="" AND objExcel.Workbooks(Str1).Sheets(1).Range("H"&i)="" AND objExcel.Workbooks(Str1).Sheets(1).Range("L"&i)="" Then
i = numLines
Else '' here i get the reference (the 6 first digits of the first workbook and I try to find it in the second)
If objExcel.Workbooks(Str1).Sheets(1).Range("D"&i)<>"" Then
Reference = Mid(objExcel.Workbooks(Str1).Sheets(1).Range("D"&i),1,6)
Set table_lookup = objExcel.Workbooks(Str1).Sheets(1).Range( "C1:C" & numLines2 )
cell = objExcel.Workbooks(Str2).WorksheetFunction.vlookup(Reference, table_lookup, 0, False)
MsgBox cell.row
MsgBox cell.column
End If
End If
Next
You have to switch to the "find" method instead of the vlookup that does not seem to work on vba
For i = 7 to numLines
If objExcel.Workbooks(Str1).Sheets(1).Range("D"&i)="" AND objExcel.Workbooks(Str1).Sheets(1).Range("H"&i)="" AND objExcel.Workbooks(Str1).Sheets(1).Range("L"&i)="" Then
i = numLines
Else
If objExcel.Workbooks(Str1).Sheets(1).Range("D"&i)<>"" Then
Reference = Mid(objExcel.Workbooks(Str1).Sheets(1).Range("D"&i),1,6)
Set r = objExcel.Workbooks(Str2).Sheets(1).Range( "C1:C" & numLines2 )
Set matched = r.Find(Reference)
If Not r.Find(Reference) Is Nothing Then
objExcel.Workbooks(Str1).Sheets(1).Range("R"&i).Value = matched.Offset(0,0).Value
objExcel.Workbooks(Str1).Sheets(1).Range("S"&i).Value = matched.Offset(0,1).Value
objExcel.Workbooks(Str1).Sheets(1).Range("T"&i).Value = matched.Offset(0,2).Value
objExcel.Workbooks(Str1).Sheets(1).Range("U"&i).Value = matched.Offset(0,3).Value
objExcel.Workbooks(Str1).Sheets(1).Range("V"&i).Value = matched.Offset(0,6).Value
End If
End If
End If
Next

VBA in Excel - If statement Counter wont work

I have been trying to get this VBA script to work to automate a task, but I cannot get it to work.
Basically, I have a big task list in excel with multiple columns and over 1000 Rows. It contains the task, who it is assigned to, and if it is open or closed.
In column H is who it assigned to and column N is whether the task is opened or closed.
I am trying to search by last name and if it is OPEN to add one to the counter. The end goal is to get a total count of how many open tasks a person has. Also, some of the cells in column N (task status) has extra text like comments, etc. I am sure that a InStr Function to search for the one word within the Cell would work better, but I cannot figure it out...
here is my code
Sub statuscount()
Dim tasksheet As Worksheet
Dim simons_count As Integer
Set tasksheet = ThisWorkbook.Sheets("tasks")
lr = tasksheet.Cells(Rows.Count, 1).End(xlUp).Row
For x = 5 to lr
If tasksheet.Cells(x, 8) = "Simons" And tasksheet.Cells(x, 14) = "OPEN" Then
simons_count = simons_count + 1
End If
Next x
tasksheet.Range("$O$5").Value = simons_count
End Sub
Thanks for the help!
Using If/And gets tricky in VBA, you're better off nesting two if statements:
For x = 5 to lr
If tasksheet.Cells(x, 8) = "Simons" Then
If InStr(tasksheet.Cells(x, 14).Value, "OPEN") > 0 Then
simons_count = simons_count + 1
End If
End If
Next x
This is a more general function. Insert a module and past the below code in it. Than you can use the function just like any other Excel built-in function
Function LastNamecounter(lastName As String, status As String) As Long
LastNamecounter = 0
Dim tasksheet As Worksheet
Set tasksheet = ThisWorkbook.Sheets("tasks")
lr = tasksheet.Cells(Rows.Count, 1).End(xlUp).Row
For i = 5 To lr
If InStr(tasksheet.Cells(i, 8).Value, lastName) <> 0 And InStr(tasksheet.Cells(i, 14).Value, status) <> 0 Then
LastNamecounter = LastNamecounter + 1
End If
Next i
End Function

Loop through Excel Ranges Filling Combobox VB.Net

I have a program that needs to iterate through a very large excel range, to combine two ranges into one combo box value. I have the following code to do so, but all it does is iterate the first value five times. If I remove the first FOR loop, then it simply only returns the first value and never completes. Any suggestions on what I can do to polish this code up and get it working?
Dim i As Integer
If TenantBox.SelectedItem = "CNS" Then
WFMBook.Workbooks.Open("C:\Schedule.xlsx")
For i = 0 To 5 Step +1
For Each CNSCell In WFMBook.Range("A3:A1441").Cells
f = CNSCell.Value.ToString
Next
For Each tst In WFMBook.Range("B3:B1441").Cells
l = tst.Value.ToString
Next
ComboBox1.Items.Add(f + " " + l)
If (i = 5) Then
Exit For
End If
Console.WriteLine(i)
Next
End If
Try this, just change the x to 1 if VBA is 1 based.
If TenantBox.SelectedItem = "CNS" Then
WFMBook.Workbooks.Open("C:\XHSchedule.xlsx")
Dim colCount = WFMBook.Range("A3:A8").Cells.Count
For x = 1 To colCount Step +1
For Each CNSCell In WFMBook.Range("A3:A8").Cells
f = WFMBook.Range("A3:A8").Cells(x).Value.ToString
l = WFMBook.Range("B3:B8").Cells(x).Value.ToString
Next
ComboBox1.Items.Add(f + " " + l)
Next
End If