I've been struggling with a minor project, yet it's supposed to be easy. I have a windows form app in vba to insert values into a excel file.
It used to work in my company cause we had just a "couple" of data to enter. But now we are using txt files to gather the data to insert them in the excel file..
My problem is that we can't use macros anymore because there's always someone that changes something in the code.
My code WAS something like this:
Dim oApp As Excel.Application
Try
oApp = DirectCast(CreateObject("Excel.Application"), Excel.Application)
oApp.Workbooks.OpenText(Filename:=TextBox1.Text, _
Origin:=Excel.XlPlatform.xlMSDOS, _
DataType:=Excel.XlTextParsingType.xlDelimited, _
Comma:=False, Semicolon:=True, _
StartRow:=1)
oApp.Visible = True
oApp.Workbooks.Item(TextBox4.Text).SaveAs(Filename:=TextBox2.Text, _
FileFormat:=Excel.XlFileFormat.xlWorkbookNormal)
oApp.Workbooks.Item(TextBox3.Text).Close(SaveChanges:=False)
'Quit Excel
oApp.Quit()
oApp = Nothing
MessageBox.Show("Success.", "Success!", MessageBoxButtons.OK)
Catch ex As Exception
MessageBox.Show(ex.Message.ToString, "Error", MessageBoxButtons.OK)
End Try
NOW i want to use a template Excel, and insert the data in sheet1, cause sheet2 has all the graphs and stuff..
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
xlWorkBook = xlApp.Workbooks.Open(TextBox2.Text)
xlApp.Visible = True
xlWorkSheet = xlWorkBook.Sheets("data")
**With xlWorkSheet
'~~> Directly type the values that we want
.Range("A1").Value = "1"
.Range("A2").Value = "2"
End With**
End Sub
and i have no idea how to implement that. i don't know how to take the txt file and "place it" in sheet1..
Thank you all!
To insert a text file line by line into excel.
Dim inFile as string() = file.ReadAllLines("yourFileName")
xlWorkBook = xlApp.Workbooks.Open(TextBox2.Text)
xlApp.Visible = True
xlWorkSheet = xlWorkBook.Sheets("data")
for x as integer = 0 to inFile.length - 1
dim splitLine as String() = infile(x).split(";"c)
For y as integer = 0 to splitLine.length - 1
xlWorkSheet.rows(x + 1).Cells(y + 1).value = splitLine(y)
Next
Next
if you just want to attach the file with an icon showing then I would use this.
xlWorkSheet.Shapes.AddOLEObject("Word.Document.8", "YourfilePath", False, False)
I believe should work.
Related
I have to export, under pressure of a button, some data in different extensions. To do this, I provided a SaveFileDialog, but depending on the filter (and so the output file extension), I have to write data with a different process:
if I have to export it as .txt or .csv, I have to use writer
otherwise if I have to export it as .xlsx, .xls or .ods I have to use NPOI
I provided the code both for writer and NPOI and they work singularly. If I try to put them together, .txt and .csv works, but for .xlsx, it exports a corrupted file.
This is the code I'm using:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
SaveFileDialog1.Filter = "TXT Files (*.txt*)|*.txt|CSV Files (*.csv*)|*.csv|Excel 2010 Workbook (*.xlsx*)|*.xlsx|Excel 2000 Workbook (*.xls*)|*.xls|OpenOffice Spreadsheet (*.ods*)|*.ods"
SaveFileDialog1.CheckFileExists = False
Dim t As Integer
t = CInt(Form10.Label13.Text)
If SaveFileDialog1.ShowDialog() = DialogResult.OK Then
If SaveFileDialog1.Filter = "TXT Files (*.txt*)|*.txt|CSV Files (*.csv*)|*.csv|" Then
Using writer = New StreamWriter(SaveFileDialog1.FileName)
For Each o As Object In Form10.ListBox2.Items
writer.WriteLine(o)
Next
End Using
End If
End If
If SaveFileDialog1.Filter = "Excel 2010 Workbook (*.xlsx*)|*.xlsx|Excel 2000 Workbook (*.xls*)|*.xls|OpenOffice Spreadsheet (*.ods*)|*.ods|" Then
Dim fs As New FileStream(SaveFileDialog1.FileName, FileMode.Create, FileAccess.Write)
Dim workbook As IWorkbook = New XSSFWorkbook()
Dim worksheet As ISheet = workbook.CreateSheet()
Dim ich As ICreationHelper = workbook.GetCreationHelper()
Dim rows As New List(Of IRow)
Dim rowz As IRow = worksheet.CreateRow(0)
rowz.CreateCell(0).SetCellValue(ich.CreateRichTextString("Time [s]"))
rowz.CreateCell(1).SetCellValue(ich.CreateRichTextString("HRR [kW]"))
For i As Integer = 1 To t
Dim row As IRow = worksheet.CreateRow(i)
row.CreateCell(0).SetCellValue(CDbl(Form10.ListBox1.Items(i)))
row.CreateCell(1).SetCellValue(CDbl(Form10.ListBox2.Items(i)))
rows.Add(row)
Next i
workbook.Write(fs)
fs.Close()
End If
End If
End Sub
I'd like to know if the "if loop" is set properly for filters. Thanks all are gonna answer me. Best regards.
Just get the file path selected by the user and check its extension, e.g.
Select Case Path.GetExtension(SaveFileDialog1.FileName)
Case ".txt", ".csv"
'...
Case ".xlsx", ".xls", ".ods"
'...
End Select
In order to speed up the export of data held in a datagridview to excel, I am using a method suggest in this forum where the contents of the datagridview are copied to the clipboard, and then pasted into the excel spreadsheet, in order to cut down on the amount of times the application has to communicate with excel.
Whilst this works fine, one draw back is that if a user has particular cells selected in the datagridview - the code will cause this selection to be lost, as it uses the datagridview.SelectAll() method.
I was hoping to find a simple solution to reselect the users original selection post exporting to excel. I have tried the following:
Dim mySelection As DataGridViewSelectedCellCollection
mySelection = myDataGridView.SelectedCells
ExportToExcel(myDataGridView, "Exported Data")
myDataGridView.SelectedCells = mySelection
I suspect that DataGridViewSelectedCellCollection is not the correct thing to use here, as it seems to be about the data held within the selection rather than the positions of the selected cells.
Alternative is there a way of getting all of the datagridview into the clipboard without having to use SelectAll()?
If needed the Export to Excel code is here:
Private Sub ExportToExcel(myDataGridView As DataGridView, myWorksheetName As String)
' Creating a Excel object.
Dim excel As Microsoft.Office.Interop.Excel._Application = New Microsoft.Office.Interop.Excel.Application()
Dim workbook As Microsoft.Office.Interop.Excel._Workbook = excel.Workbooks.Add(Type.Missing)
Dim xlWorkSheet As Microsoft.Office.Interop.Excel._Worksheet = Nothing
Try
xlWorkSheet = workbook.ActiveSheet
xlWorkSheet.Name = myWorksheetName
'Data transfer from grid to Excel.
With xlWorkSheet
.Range("1:1").EntireRow.Font.Bold = True
'Set Clipboard Copy Mode
myDataGridView.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
myDataGridView.SelectAll()
'Get the content from Grid for Clipboard
Dim str As String = TryCast(myDataGridView.GetClipboardContent().GetData(DataFormats.UnicodeText), String)
'Set the content to Clipboard
Clipboard.SetText(str, TextDataFormat.UnicodeText)
'Identify and select the range of cells in Excel to paste the clipboard data.
.Range("A1").Select()
'Paste the clipboard data
.Paste()
Clipboard.Clear()
End With
'Getting the location and file name of the excel to save from user.
Dim saveDialog As New SaveFileDialog()
saveDialog.Filter = "Excel files (*.xlsx)|*.xlsx"
saveDialog.FilterIndex = 2
If saveDialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
workbook.SaveAs(saveDialog.FileName)
MessageBox.Show("Export Successful")
End If
Catch ex As System.Exception
MessageBox.Show(ex.Message)
Finally
excel.Quit()
workbook = Nothing
excel = Nothing
End Try
End Sub
You can copy the contents of the DataGridView without changing the selection. Do this by assembling a tab-delimited unicode String and pushing it into the ClipBoard:
Sub CopyDataGridViewToClipboard(dgv As DataGridView, includeHeader As Boolean)
Dim sbl As New System.Text.StringBuilder
If includeHeader Then
For intCol As Integer = 0 To dgv.Columns.Count - 1
Dim dgvc As DataGridViewColumn = dgv.Columns(intCol)
If intCol > 0 Then sbl.Append(vbTab)
sbl.Append(dgvc.HeaderText)
Next intCol
sbl.AppendLine()
End If
For intRow As Integer = 0 To dgv.Rows.Count - 1
Dim dgvr As DataGridViewRow = dgv.Rows(intRow)
For intCol As Integer = 0 To dgv.Columns.Count - 1
If intCol > 0 Then sbl.Append(vbTab)
sbl.Append(dgvr.Cells(intCol).Value)
Next intCol
sbl.AppendLine()
Next intRow
Clipboard.SetText(sbl.ToString, TextDataFormat.UnicodeText)
End Sub
Since DGV.SelectedCells is readonly, I think you may just have to set each cell's selected property to true individually (unless you're doing full row/column selection). You could just iterate through your Selected Cells Collection, and reselect each one:
myDataGridView.ClearSelection()
If mySelection IsNot Nothing Then
For Each dgvCell As DataGridViewCell In mySelection
dgvCell.Selected = True
Next
mySelection = Nothing
End If
I'm trying to add the functionality in my Outlook (with VBA, I guess is easiest) to add a simple file dialog which takes the path of any files chosen and adds them to the email body as a hyperlink.
The idea of this is for network files to be shared amongst colleagues, instead of attaching them to the email, but just as easy to do.
This is my code so far, I can't even get the dialog to open, and I've had a good look at trying to get COMDLG32.ocx, so far I can't seem to make anything work.
Sub Main2()
Dim CDLG As Object
Set CDLG = CreateObject("MSComDlg.CommonDialog")
With CDLG
.DialogTitle = "Get me a File!"
.Filter = _
"Documents|*.doc|Templates|*.dot|Text Files|*.txt"
.ShowOpen
MsgBox .FileName
End With
Set CDLG = Nothing
End Sub
Thanks in advance, hopefully someone can show me how this is done!
Just for those who need it; OS Windows 10, Office 2010 H&B (yes, I know it's out of date :))
There seems to be no direct way to open a FileDialog in Outlook 2010 VBA.
The following macro (inspired by a related post) makes use of Excel to circumvent this:
Public Function promptFileName(title As String, filter As String) As String
' requires project reference to "Microsoft Excel 14.0 Object Library"
Dim xlObj As Excel.Application
Dim fd As Office.FileDialog
Dim name As String
Dim vItem As Variant
Dim filterArray() As String
Dim i As Integer
Set xlObj = New Excel.Application
xlObj.Visible = False
Set fd = xlObj.Application.FileDialog(msoFileDialogOpen)
name = ""
With fd
.title = title
.ButtonName = "Ok"
.Filters.Clear
filterArray = Split(filter, "|")
For i = LBound(filterArray) To UBound(filterArray) - 1 Step 2
.Filters.Add filterArray(i), filterArray(i + 1), 1 + i \ 2
Next i
If .Show = -1 Then
For Each vItem In .SelectedItems
name = vItem
Exit For
Next
End If
End With
xlObj.Quit
Set xlObj = Nothing
promptFileName = name
End Function
Private Sub testPromptFile
Dim name as String
name = promptFileName("a test", "Text Files (*.txt)|*.txt|All Files (*.*)|*.*")
MsgBox name
End Sub
Outlook 2013 and beyond provide an Office.FileDialog class for this purpose.
You can press a button with Outlook VBA.
Sub ExecuteMso_strId()
Dim objItem As Object
Dim strId As String
' Text appears when hovering over icon
' when adding buttons to a Quick Access toolbar or a ribbon
strId = "HyperlinkInsert"
On Error Resume Next
Set objItem = ActiveInspector.currentItem
On Error GoTo 0
If Not objItem Is Nothing Then
ActiveInspector.CommandBars.ExecuteMso (strId)
Else
ActiveExplorer.CommandBars.ExecuteMso (strId)
End If
End Sub
With this you do not have access to the parameters as with Excel.
I need help with saving user entered data (textbox) to an excel file. The excel file should be created on desktop automatically. I can add one textbox to excel but not multiple. If possible can you give code on being able to open the same file when btnopen is clicked, thank you!
my code right now for save button.
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
SaveFileDialog.Filter = "CSV Files (*.csv*)|*.csv"
If SaveFileDialog.ShowDialog = Windows.Forms.DialogResult.OK _
Then
My.Computer.FileSystem.WriteAllText _
(SaveFileDialog.FileName, txtBMI.Text, True)
End If
table.Rows.Add(DateTimePicker1.Text, txtBMI.Text, txtHeight.Text, txtWeight.Text)
DataGridView1.DataSource = table
End Sub
http://i.stack.imgur.com/H73M8.jpg
http://i.stack.imgur.com/Rjtjw.jpg
I think you need to use a supported library of creating Excel file and not to do it with file.create as you did.
You can use Microsoft Excel 12.0 Object Library and add a refernce to the bin folder or other dll of working with Excel instance.
Dim xlApp As Excel.Application = New
Microsoft.Office.Interop.Excel.Application()
You can see it here -
http://vb.net-informations.com/excel-2007/vb.net_excel_2007_create_file.htm
Add first the Microsoft Excel 12.0 Object Library via
Project>Properties>References>Add>COM>Type Libraries>Microsoft Excel 12.0 Object Library
Add releaseObject function (To release the excel file in the app):
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
After adding, declare the necessary variables so that it's easier to control the excel file:
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")
' Add a new workbook.
wbXl = appXL.Workbooks.Add
shXL = wbXl.ActiveSheet
shXL.PageSetup.Orientation = Excel.XlPageOrientation.xlLandscape
shXL.PageSetup.PaperSize = Excel.XlPaperSize.xlPaperA3
appXL.Visible = False
Add the headers with bold text:
With shXL.Range("A1", "D1")
.Font.Bold = True
End With
shXL.Cells(1,1) = "Date"
shXL.Cells(1,2) = "Height"
shXL.Cells(1,3) = "Weight"
shXL.Cells(1,4) = "BMI"
shXL.Cells(2,1) = DateTimePicker1.Text
shXL.Cells(2,2) = txtHeight.Text
shXL.Cells(2,3) = txtWeight.Text
shXL.Cells(2,4) = txtBMI.Text
Next, open the excel file.
appXL.Visible = True
appXL.UserControl = True
shXL.SaveAs("C:\Book1.xml")
raXL = Nothing
shXL = Nothing
wbXl = Nothing
appXL = Nothing
releaseObject(shXL)
releaseObject(wbXl)
releaseObject(appXL)
I am trying to write a code that exports data to excel after user prompted actions.
Basically, I have been able to export to Excel successfully, but the 2nd instance I want to write to a new tab instead of a new Excel application.
oExcel = CreateObject("Excel.Application")
oExcel.Visible = True
oBook = oExcel.Workbooks.Add
oSheet = oBook.Worksheets(3)
oSheet.Delete()
oSheet = oBook.Worksheets(2)
oSheet.Delete()
oSheet = oBook.Worksheets(1)
oSheet.Name = "Run " & Counter
At this point, the user will press a button, making Excel no longer active.
So when I want to write more data to a new sheet, the Object commands do not
'work unless I repeat code exactly.
I tried:
Counter +=1
'For the first instance
If Counter = 1 Then
oExcel = CreateObject("Excel.Application")
oExcel.Visible = True
oBook = oExcel.Workbooks.Add
oSheet = oBook.Worksheets(3)
oSheet.Delete()
oSheet = oBook.Worksheets(2)
oSheet.Delete()
oSheet = oBook.Worksheets(1)
oSheet.Name = "Run " & Counter
Else
'For every instance after that the user wants to do another run
oExcel.ActivateObject(Excel.Application)
oBook = oExcel.Workbooks(1)
oSheet = oBook.Worksheets.Add
oSheet.Name = "Run " & Counter
End If
I have been looking for days and am getting very frustrated. I do not know how to reference back to the open excel in order to continue to writing data ... after the user has pressed a button on the VB form confirming they want to do another run.
To get a reference to an already-running instance of excel you can use GetObject.
Eg:
' Test to see if a copy of Excel is already running.
Private Sub testExcelRunning()
On Error Resume Next
' GetObject called without the first argument returns a
' reference to an instance of the application. If the
' application is not already running, an error occurs.
Dim excelObj As Object = GetObject(, "Excel.Application")
If Err.Number = 0 Then
MsgBox("Excel is running")
Else
MsgBox("Excel is not running")
End If
Err.Clear()
excelObj = Nothing
End Sub
http://msdn.microsoft.com/en-us/library/e9waz863(v=vs.90).aspx
If Excel is not already running you can start a new instance using CreateObject.
I used to write VBA, but I was taught to get out of the habit of using CreateObject. you could also use a boolean just as well, but i imagine thats just preference. You should create the excel object outside the loop, hold reference at class level once its assigned. you then use the loop to solely assign the next sheets and add values. Keeping the dimension at class level means you do not need to get rid of the object immediately, because there is possibility the user might still need to use the reference.
Public Class Form1
Dim firstRun As Boolean = True
Dim xlApp As New Excel.Application
Dim xlWb As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'set up us some excel
xlApp.Visible = True
xlApp.SheetsInNewWorkbook = 1
xlWb = xlApp.Workbooks.Add
'imaginary loop
For i = 0 To 5
Dim msgResponse = MessageBox.Show("Do you want to loop?", "Keep Looping?", MessageBoxButtons.YesNo)
If msgResponse = Windows.Forms.DialogResult.No Then Exit For
If firstRun Then
xlSheet = xlWb.Sheets(1)
firstRun = False
Else
xlWb.Activate()
xlSheet = xlWb.Sheets.Add(After:=xlWb.Sheets(xlWb.Sheets.Count))
End If
xlSheet.Name = "TEST" & i
xlSheet.Range("A1").Value = "Some Data"
Next i
End Sub
End Class
You will need to make sure that you clean up your references once you are certain the user is done with the sheet.