it's my first approach to openxml and I can't get it to work.
Hi want to create an xls file, write a value to specific cells and save it. This is the code I wrote for now, it creates the file but doesn't write any value at all. What I'm missing? Thanks
EDIT: as asked I addedd InsertCellInWorksheet function
Sub Main()
CreateSpreadsheetWorkbook("IMPOVO.XLS")
Dim spreadSheet As SpreadsheetDocument = SpreadsheetDocument.Open("IMPOVO.XLS", True)
Using (spreadSheet)
Dim worksheetPart As WorksheetPart = spreadSheet.WorkbookPart.WorksheetParts.First
Dim cell As Cell = InsertCellInWorksheet("A", 1, worksheetPart)
' Set the value of cell A1.
cell.CellValue = New CellValue("Hi World")
cell.DataType = New EnumValue(Of CellValues)(CellValues.SharedString)
' Save the new worksheet.
worksheetPart.Worksheet.Save()
End Using
End Sub
Public Sub CreateSpreadsheetWorkbook(ByVal filepath As String)
'Create a spreadsheet document by supplying the filepath.
'By default, AutoSave = true, Editable = true, and Type = xlsx.
Dim spreadsheetDocument As SpreadsheetDocument =
SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)
'Add a WorkbookPart to the document.
Dim workbookpart As WorkbookPart = spreadsheetDocument.AddWorkbookPart
workbookpart.Workbook = New Workbook
'Add a WorksheetPart to the WorkbookPart.
Dim worksheetPart As WorksheetPart = workbookpart.AddNewPart(Of WorksheetPart)()
worksheetPart.Worksheet = New Worksheet(New SheetData())
'Add Sheets to the Workbook.
Dim sheets As Sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild(Of Sheets)(New Sheets())
'Append a new worksheet and associate it with the workbook.
Dim sheet As Sheet = New Sheet
sheet.Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart)
sheet.SheetId = 1
sheets.Append(sheet)
workbookpart.Workbook.Save()
'Close the document.
spreadsheetDocument.Close()
End Sub
Private Function InsertCellInWorksheet(ByVal columnName As String, ByVal rowIndex As UInteger, ByVal worksheetPart As WorksheetPart) As Cell
Dim worksheet As Worksheet = worksheetPart.Worksheet
Dim sheetData As SheetData = worksheet.GetFirstChild(Of SheetData)()
Dim cellReference As String = (columnName + rowIndex.ToString())
' If the worksheet does not contain a row with the specified row index, insert one.
Dim row As Row
If (sheetData.Elements(Of Row).Where(Function(r) r.RowIndex.Value = rowIndex).Count() <> 0) Then
row = sheetData.Elements(Of Row).Where(Function(r) r.RowIndex.Value = rowIndex).First()
Else
row = New Row()
row.RowIndex = rowIndex
sheetData.Append(row)
End If
' If there is not a cell with the specified column name, insert one.
If (row.Elements(Of Cell).Where(Function(c) c.CellReference.Value = columnName + rowIndex.ToString()).Count() > 0) Then
Return row.Elements(Of Cell).Where(Function(c) c.CellReference.Value = cellReference).First()
Else
' Cells must be in sequential order according to CellReference. Determine where to insert the new cell.
Dim refCell As Cell = Nothing
For Each cell As Cell In row.Elements(Of Cell)()
If (String.Compare(cell.CellReference.Value, cellReference, True) > 0) Then
refCell = cell
Exit For
End If
Next
Dim newCell As Cell = New Cell
newCell.CellReference = cellReference
row.InsertBefore(newCell, refCell)
worksheet.Save()
Return newCell
End If
End Function
This is just a suggestion, but try explicitly closing the document at the end of the Using block like your code does in the last instruction in the CreateSpreadsheetWorkbook() method to see if that resolved the issue. You may also need to explicitly save the spreadsheet object at the end of the Using block.
Related
I have created a macro to import data from another workbook, but i have to set which row to start. I was wondering how i would alter the code to paste the import data to the last empty row (so its adding to the table).
Currently the macro, prompts to click the file you would like to import, then imports the data from certain col from source WB to target WB. But as you can see it as been assigned the row to paste. My question is how do i get it to paste at the last empty row, so it is collecting the data rather then over writing the data.
Would i need to change the "targetSheet.Range("R2", "R4000").Value = sourceSheet.Range("Q2", "Q4000").Value"
Public Sub Extract_Excel_file()
''//--------------------------------------------
' Get customer workbook...
Dim customerBook As Workbook
Dim filter As String
Dim caption As String
Dim customerFilename As String
Dim customerWorkbook As Workbook
Dim targetWorkbook As Workbook
' make weak assumption that active workbook is the target
Set targetWorkbook = Application.ActiveWorkbook
' get the customer workbook
filter = "Text files (*.xlsx),*.xlsx"
caption = "Please Select an input file "
customerFilename = Application.GetOpenFilename(filter, , caption)
Set customerWorkbook = Application.Workbooks.Open(customerFilename)
' assume range is A1 - C10 in sheet1
' copy data from customer to target workbook
Dim targetSheet As Worksheet
Set targetSheet = ThisWorkbook.Sheets("Raw Data")
Dim sourceSheet As Worksheet
Set sourceSheet = customerWorkbook.Worksheets(1)
sourceSheet.Range("A2", "V400").NumberFormat = "#" ''//Set all cells to
text format.
' sourceSheet.Range("A2", "A4000").NumberFormat = "#" ''//Set all cells
to text format.
targetSheet.Range("B2", "B4000").Value = sourceSheet.Range("A2",
"A4000").Value
targetSheet.Range("C2", "C4000").Value = sourceSheet.Range("B2",
"B4000").Value
targetSheet.Range("D2", "D4000").Value = sourceSheet.Range("C2",
"C4000").Value
targetSheet.Range("E2", "E4000").Value = sourceSheet.Range("D2",
"D4000").Value
targetSheet.Range("F2", "F4000").Value = sourceSheet.Range("E2",
"E4000").Value
targetSheet.Range("G2", "G4000").Value = sourceSheet.Range("F2",
"F4000").Value
targetSheet.Range("H2", "H4000").Value = sourceSheet.Range("G2",
"G4000").Value
targetSheet.Range("I2", "I4000").Value = sourceSheet.Range("H2",
"H4000").Value
targetSheet.Range("J2", "J4000").Value = sourceSheet.Range("I2",
"I4000").Value
targetSheet.Range("K2", "K4000").Value = sourceSheet.Range("J2",
"J4000").Value
targetSheet.Range("L2", "L4000").Value = sourceSheet.Range("K2",
"K4000").Value
targetSheet.Range("M2", "M4000").Value = sourceSheet.Range("L2",
"L4000").Value
targetSheet.Range("N2", "N4000").Value = sourceSheet.Range("M2",
"M4000").Value
targetSheet.Range("O2", "O4000").Value = sourceSheet.Range("N2",
"N4000").Value
targetSheet.Range("P2", "P4000").Value = sourceSheet.Range("O2",
"O4000").Value
targetSheet.Range("L2", "L4000").Value = sourceSheet.Range("P2",
"P4000").Value
targetSheet.Range("Q2", "Q4000").Value = sourceSheet.Range("L2",
"L4000").Value
targetSheet.Range("R2", "R4000").Value = sourceSheet.Range("Q2",
"Q4000").Value
' Close customer workbook
Application.DisplayAlerts = False ''//Don't promt to Save
customerWorkbook.Close
Application.DisplayAlerts = True '' undo Don't promt to Save
End Sub
I just want it to collect the data rather then overriding it each month.
i have a comma delimited text file as follows
RLGAcct#,PAYMENT_AMOUNT,TRANSACTION_DATE,CONSUMER_NAME,CONSUMER_ADD_STREET,CONSUMER_ADD_CSZ,CONSUMER_PHONE,CONSUMER_EMAIL,LAST_FOUR
ZTEST01,50.00,11/15/2018,ROBERT R SMITH,12345 SOME STREET,60046,,adam#adamparks.com,2224
ZTEST02,100.00,11/15/2018,ROBERT JONES,5215 OLD ORCHARD RD,60077,,adam#adamparks.com,2223
ZTEST03,75.00,11/15/2018,JAMES B MCDONALD,4522 N CENTRAL PARK AVE APT 2,60625,,adam#adamparks.com,2222
ZTEST04,80.00,11/15/2018,JOHN Q DOE,919 W 33RD PL 2ND FL,60608,,adam#adamparks.com,2221
ZTEST05,60.00,11/15/2018,SAMANTHAN STEVENSON,123 MAIN ST,60610,,adam#adamparks.com,2220
I need to export this to excel so that each value between a comma is inserted into a column in excel
So
ZTEST01 is in A1,
50.00 is in B1
11/15/2018 in C1 ...
The thing is i need each row to be inserted into a newly created excel worksheet.
The code i have is as follows:
Dim xlApp As New Excel.Application
Dim xlWorkbook As Excel.Workbook
Dim xlWorksheet As Excel.Worksheet
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'xlWorkbook = xlApp.workboos.Add() using this later once i have the parsing figured out
Dim columns As New List(Of String)
Dim ccPayment = "C:\Users\XBorja.RESURGENCE\Downloads\Payments_Credit.txt"
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(ccPayment)
MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
MyReader.Delimiters = New String() {","}
Dim currentRow As String()
'Loop through all of the fields in the file.
'If any lines are corrupt, report an error and continue parsing.
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
' Include code here to handle the row.
For Each r In currentRow
columns.Add(r)
C
Next r
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
'Dim index0 = columns(0)
'Dim index1 = columns(1)
'Dim index2 = columns(3)
'Dim index3 = columns(3)
'Dim index4 = columns(4)
'Dim index5 = columns(5)
'Dim index6 = columns(6)
'Dim index7 = columns(7)
'Dim index8 = columns(8)
'Console.WriteLine(index0 & index1 & index2 & index3 & index4 & index5 & index6 & index7 & index8)
End Using
For Each r In columns
Console.WriteLine(r)
Next
end sub
As you can see I was trying to see if i could index these so that i could possibly equate each one to a cell in excel.
The other problem is that this text file changes daily. The columns are always set (9 columns) but the rows change dynamically daily based on how many transactions we get.
I would recommend using the EPPlus package which is available via NuGet. It removes the COM challenges of working with Excel and works by reading and writing the XLSX spreadsheet files.
The following sample does what you where asking:
Private Sub btnStackOverflowQuestion_Click(sender As Object, e As EventArgs) Handles btnStackOverflowQuestion.Click
Dim ccPayment As String = "C:\temp\so.csv"
Using pkg As New ExcelPackage()
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser(ccPayment)
MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
MyReader.Delimiters = New String() {","}
Dim sheetCount As Integer
While Not MyReader.EndOfData
sheetCount += 1
Dim newSheet As ExcelWorksheet = pkg.Workbook.Worksheets.Add($"Sheet{sheetCount}")
Try
Dim currentRow As String() = MyReader.ReadFields()
Dim columnCount As Integer = 0
For Each r In currentRow
columnCount += 1
newSheet.Cells(1, columnCount).Value = r
Next r
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
End While
End Using
Dim fi As New FileInfo("C:\temp\so.xlsx")
pkg.SaveAs(fi)
End Using
End Sub
I want to grab data from an Edit Text box from other workbooks and insert it into a single worksheet in a different workbook.
Sub TransferCompanyNames()
for(int i = 0; i < 479; i++){
variable = Workbooks.Open Range(//Column A with index i);
//column a contains a link to the workbook C:/Users/.../Documents/file.xlsx
//grab data from Edit Text Box and insert into current sheet at column A with index i
}
End Sub
I understand that this isn't the correct syntax.
Something like this perhaps:
Sub TransferCompanyNames()
Dim i As Integer
Dim SourceBook As Workbook
Dim TargetSheet As Worksheet
Set TargetSheet = Workbooks("ChangeToYourWorkbookName").Worksheets("ChangeToYourSheetName")
For i = 1 To 480
Set SourceBook = Workbooks.Open(Range("A" & i).Value)
TargetSheet.Range("B" & i).Value = ActiveSheet.Shapes(1).TextFrame.Characters(1, _
ActiveSheet.Shapes(1).TextFrame.Characters.Count).Text
SourceBook.Close False
Next
End Sub
I'm developing a windows forms written in VB.NET.
In a form I need to import an Excel file and read it's data then show or store it in database. When I get cells containing numbers, the value is right but when I get cells containing strings, it just returns single digit numbers.
Here is the code :
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim frm_sample As New frm_saple_importexcel
frm_sample.ShowDialog()
Dim ofd As New OpenFileDialog
ofd.Filter = $"Excel File (*.xlsx)|*.xlsx|Excel File (*.xls)|*.xls|All files (*.*)|*.*"
ofd.ShowDialog()
Using spreadsheetDocument As SpreadsheetDocument =
SpreadsheetDocument.Open(ofd.FileName, False)
Dim dtSet As DataSet = New DataSet("JustAName")
Dim workbookPart As WorkbookPart = spreadsheetDocument.WorkbookPart
Dim worksheetPart As WorksheetPart = workbookPart.WorksheetParts.First()
Dim sheetData As SheetData = worksheetPart.Worksheet.Elements(Of SheetData)().First()
Dim dt = New DataTable("tt")
dt.Columns.Add(New DataColumn("k_code"))
dt.Columns.Add(New DataColumn("k_name"))
dt.Columns.Add(New DataColumn("k_unit"))
dt.Columns.Add(New DataColumn("k_group_name"))
For Each r As Row In sheetData.Elements(Of Row)()
Dim row As DataRow = dt.NewRow
row("k_code") = r.ChildElements.ElementAt(0).InnerText
row("k_name") = r.ChildElements.ElementAt(1).InnerText
row("k_unit") = r.ChildElements.ElementAt(2).InnerText
row("k_group_name") = r.ChildElements.ElementAt(3).InnerText
dt.Rows.Add(row)
Next
dtSet.Tables.Add(dt)
DataGridView1.DataSource = dtSet.Tables(0)
End Using
End Sub
UPDATED:
Appeared to be something with the SHEETID, now its finding additional worksheets when working with the USING tag instead in combo with this sheetid finder.
Dim sheetId As UInteger = 1
If (sheets.Elements(Of Sheet).Count > 0) Then
sheetId = CUInt(sheets.Elements(Of Sheet).Select(Function(s) s.SheetId.Value).Max + 1)
End If
Here is the code i used to make it work, stopped corrupting the file now:
' Given a document name, inserts a new worksheet.
Public Sub InsertWorksheet(ByVal docName As String, ByVal SQL As DataTable, ByVal sheetName As String, ByVal intSheetId As Integer)
'Dim sheetName As String
Dim fileName As String = docName
' Open an existing spreadsheet document for editing.
Dim spreadSheet As SpreadsheetDocument = SpreadsheetDocument.Open(fileName, True)
Using (spreadSheet)
' Add a blank WorksheetPart.
Dim newWorksheetPart As WorksheetPart = spreadSheet.WorkbookPart.AddNewPart(Of WorksheetPart)()
newWorksheetPart.Worksheet = New Worksheet(New SheetData())
' Create a Sheets object.
Dim sheets As Sheets = spreadSheet.WorkbookPart.Workbook.GetFirstChild(Of Sheets)()
Dim relationshipId As String = spreadSheet.WorkbookPart.GetIdOfPart(newWorksheetPart)
' Get a unique ID for the new worksheet.
Dim sheetId As UInteger = 1
If (sheets.Elements(Of Sheet).Count > 0) Then
sheetId = CUInt(sheets.Elements(Of Sheet).Select(Function(s) s.SheetId.Value).Max + 1)
End If
' Append the new worksheet and associate it with the workbook.
Dim sheet As Sheet = New Sheet
sheet.Id = relationshipId
sheet.SheetId = sheetId
sheet.Name = sheetName
sheets.Append(sheet)
'get the sheetData object so we can add the data table to it
Dim sheetData As SheetData = newWorksheetPart.Worksheet.GetFirstChild(Of SheetData)()
'add the data table
AddDataTable(SQL, sheetData)
'save the workbook
newWorksheetPart.Worksheet.Save()
' Close the document.
spreadSheet.Close()
End Using
End Sub
File is always corrupt after creating, trying to create a spreadsheet with 4 workbooks with separate data loaded via data tables. File size looks to be valid and I dont get any specific errors when creating the file. Just won't open the excel sheet after creating the file.
Existing code to call functions:
Try
CreateExcelFileFromDataTable(iExcelFileLoc & ExportFileName, iAGetTable)
Catch ex As Exception
Dim ExceptionType As Integer = Type.GetTypeCode(ex.GetType())
LogMessage(strAppName & " - Failure : " & iExcelFileLoc & ExportFileName & " Error:'" & ex.Message & "' Error Type:'" & CStr(ExceptionType) & "' Trace:" & ex.StackTrace, TraceEventType.Error)
End Try
Dim iBGetTable As DataTable = GetDataTable(SQL_SELECT_DOCUMENTS_TO_FOR_DOCS_NOT_FOUND_IN_DOCNUMS)
Dim iReportB As String = BuildReportHTML(iBGetTable)
InsertWorksheet(iExcelFileLoc & ExportFileName, iBGetTable, "Missing Scanned Documents", 2)
' ======================================================================
Both functions to create excel initially and then a function to add a new worksheet with datatable to the existing spreadsheet.
Public Sub InsertWorksheet(ByVal docName As String, ByVal SQL As DataTable, ByVal sheetName As String, ByVal intSheetId As Integer)
Dim iFinalSheetName As String = ""
Dim spreadSheet As SpreadsheetDocument = SpreadsheetDocument.Open(docName, True)
Dim newWorksheetPart As WorksheetPart = spreadSheet.WorkbookPart.AddNewPart(Of WorksheetPart)()
newWorksheetPart.Worksheet = New Worksheet(New SheetData())
' Add Sheets to the Workbook.
Dim sheets As Sheets = spreadSheet.WorkbookPart.Workbook.AppendChild(Of Sheets)(New Sheets())
Dim relationshipId As String = spreadSheet.WorkbookPart.GetIdOfPart(newWorksheetPart)
' Append a new worksheet and associate it with the workbook.
Dim sheetId As UInteger = 1
If (sheets.Elements(Of Sheet).Count > 0) Then
sheetId = CUInt(sheets.Elements(Of Sheet).Select(Function(s) s.SheetId.Value).Max + 1)
End If
iFinalSheetName = (sheetName.ToString())
' Append the new worksheet and associate it with the workbook.
Dim sheet As Sheet = New Sheet
sheet.Id = relationshipId
sheet.SheetId = CType(intSheetId, UInt32Value)
sheet.Name = iFinalSheetName
sheets.Append(sheet)
'get the sheetData object so we can add the data table to it
Dim sheetData As SheetData = newWorksheetPart.Worksheet.GetFirstChild(Of SheetData)()
'add the data table
AddDataTable(SQL, sheetData)
'save the workbook
newWorksheetPart.Worksheet.Save()
' Close the document.
spreadSheet.Close()
End Sub
Public Sub CreateExcelFileFromDataTable(ByVal FilePath As String, myDT As DataTable)
' Create a spreadsheet document by supplying the filepath.
' By default, AutoSave = true, Editable = true, and Type = xlsx.
Dim spreadsheetDocument As SpreadsheetDocument = spreadsheetDocument.Create(FilePath, SpreadsheetDocumentType.Workbook)
' Add a WorkbookPart to the document.
Dim workbookpart As WorkbookPart = spreadsheetDocument.AddWorkbookPart
workbookpart.Workbook = New Workbook
' Add a WorksheetPart to the WorkbookPart.
Dim worksheetPart As WorksheetPart = workbookpart.AddNewPart(Of WorksheetPart)()
worksheetPart.Worksheet = New Worksheet(New SheetData())
' Add Sheets to the Workbook.
Dim sheets As Sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild(Of Sheets)(New Sheets())
' Append a new worksheet and associate it with the workbook.
Dim sheet As Sheet = New Sheet
sheet.Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart)
sheet.SheetId = 1
sheet.Name = "Duplicate Document"
sheets.Append(sheet)
'get the sheetData object so we can add the data table to it
Dim sheetData As SheetData = worksheetPart.Worksheet.GetFirstChild(Of SheetData)()
'add the data table
'AddDataTable(myDT, sheetData)
'save the workbook
workbookpart.Workbook.Save()
' Close the document.
spreadsheetDocument.Close()
' -----------------------------------
End Sub
Here's an option for you:
Create a sample of the spreadsheet manually.
Download and Install the Open XML SDK tool
Open the spreadsheet in the tool
Once the spreadsheet is opened, there's a section where you can view .NET source code to create a sheet that looks like it.
I use the tool a lot. Working with the Office XML SDK without it can be very cumbersome.