I am having trouble with the Open XML SDK opening and saving word documents.
I am using the following code (VB.Net):
Try
'Set Path
Dim openPath As String = "../Documents/" & worddoc
Dim savePath As String = "\\web-dev-1\HR_Documents\" & worddoc
Using doc As WordprocessingDocument = WordprocessingDocument.Open("/Documents/" & worddoc, True)
'Employee Name Insert
'Find first table in document
Dim tbl1 As Table = doc.MainDocumentPart.Document.Body.Elements(Of Table).First()
'First Row in tbl
Dim row As TableRow = tbl1.Elements(Of TableRow)().ElementAt(0)
'Find first cell in row
Dim cell As TableCell = row.Elements(Of TableCell)().ElementAt(0)
'Insert selected Employee Name
Dim p As Paragraph = cell.Elements(Of Paragraph)().First()
Dim r As Run = p.Elements(Of Run)().First()
Dim txt As Text = r.Elements(Of Text)().First()
txt.Text = ddlEmployeeList.SelectedItem.Text
'Save File
'Supervisor Name Insert
'Find second table in document
Dim tbl2 As Table = doc.MainDocumentPart.Document.Body.Elements(Of Table).First()
'First Row in tbl
Dim row2 As TableRow = tbl2.Elements(Of TableRow)().ElementAt(0)
'Find first cell in row
Dim cell2 As TableCell = row2.Elements(Of TableCell)().ElementAt(0)
'Insert selected Employee Name
Dim p2 As Paragraph = cell2.Elements(Of Paragraph)().First()
Dim r2 As Run = p2.Elements(Of Run)().First()
Dim txt2 As Text = r2.Elements(Of Text)().First()
txt2.Text = ddlSupervisorList.SelectedItem.Text
End Using
Return 1
Catch ex As Exception
Return Nothing
End Try
The trouble starts on the first using statement. It throws the following error:
Could not find a part of the path 'C:\Documents\Hourly_Employee_Performance_Review .docx
I have placed the word documents in a folder of the ASP.NET site called Documents. I also have created a public share on the dev server to see if maybe that would help.
The problem is that it doesn't use the supplied path variable. I have gone through the documentation for OPEN XMl SDK but all it talks about is the Using Statement and its need and use for it.
Can anyone tell me, show me, or point to a site that has examples of how to set both the open path and save path?
You need a path to the file which is based on the filesytem, not a URL. You can do that with
Dim openPath As String = Path.Combine(Server.MapPath("~/Documents"), worddoc)
And then to open the file:
Using doc As WordprocessingDocument = WordprocessingDocument.Open(openPath, True)
It appears that you will need to do the same for the location to save to, but you didn't say if "\\web-dev-1" is a different server; if it were that would need other considerations.
(Not tested, some typos may exist. You will need an Imports System.IO.)
Related
I have trouble with the following tasks in excel VBA:
At my work, we use a document management platform called TeamShare: [https://www.lector.dk/en/products/]
I want to create a code in VBA, that loops over a range of links to this document management platform in my workbook, ie. loops over other workbooks, opens them and then copies a specified sheet to my current workbook.
I have tried putting together bits of codes from other sites, and the code works just fine when i run it in break mode. However, when I run the code all at once, the Excel program reopens, such that the current workbook cannot "communicate" with the opened workbook and I end up in an infinity loop (so no direct error message).
This is the code that only works in break mode:
Dim wbCopyTo As Workbook Dim wsCopyTo As Worksheet Dim i As Long Dim Count As Long Dim WBCount As Long Dim LastRow As Long Dim wb As Workbook Dim ws As Worksheet Dim URL As String Dim IE As Object Dim doc As Object Dim objElement As Object Dim objCollection As Object
Set wbCopyTo = ActiveWorkbook Set wsCopyTo = ActiveSheet
LastRow = wsCopyTo.Range("B" & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
The purpose of this piece of code is to get the DocID
A = InStr(wsCopyTo.Range("B" & i), "documentid=") + Len("documentid=")
B = InStrRev(wsCopyTo.Range("B" & i), "&")
DocID = Mid(wsCopyTo.Range("B" & i), A, B - A)
'Get URL
URL = wsCopyTo.Range("B" & i)
'Count number of open workbooks
WBCount = Workbooks.Count
With IE
New is the comman that opens excel sheet. This works as planned in breakmode, however the excel program reopens when i run the code all at once. I have tried other commandos here: "Workbooks.Open", I couldn't get this one to open the file and "Application.FollowHyperlink" only worked in break mode too, however, much much slower
.Navigate URL
'This was my solution to how to stop the rest of the code from executing until the new workbook has loaded.
Do Until Workbooks.Count = WBCount + 1: Loop
End With
'Unload IE
Set IE = Nothing
Set objElement = Nothing
Set objCollection = Nothing
'So in order to activate the workbook from the URL, I am looping over all my open workbooks and matching them on their unique Document ID. I found that the workbook from the URL wasn´t the "active workbook" per default.
For Each book In Workbooks If Mid(book.Name, 12, Len(DocID)) = DocID Then
book.Activate
Set wb = ActiveWorkbook
Set ws = ActiveSheet
End If
Next book
Here i copy the desired sheet to my initial workbook
wb.Worksheets("SpecificSheetIWantToCopy").Copy After:=wbCopyTo.Worksheets("Sheet1") wbCopyTo.Sheets(ActiveSheet.Name).Name = DocID
Next i
End Sub
I am using excel 2010.
I hope you can help me resolve this problem. Please ask if you need any more information, that i haven´t provided.
Thanks in advance.
Here is the situation:
Asp.Net Web Forms site using Open XML to read in a (via a stream) word document (docx). I then insert some text into the document and then write the file back out to a different location. It is then emailed to an end user. All of this works great.
The problem i am running into is that I can't the new file written by the site. I receive the following error:
"The process cannot access the file (file name here) because it is being used nt another process"
I have confirmed that it is the site (or IIS) that is holding on to the file.
Here is the code that reads the original file and generates the new file:
Private Function GetDocument(worddoc As String) As Integer
Dim byteArray As Byte() = File.ReadAllBytes("\\WEB-DEV-1\HR_Documents\" & worddoc)
Using Stream As New MemoryStream()
Stream.Write(byteArray, 0, CInt(byteArray.Length))
Try
'Set Row & Cell variables
Dim rowNum As Integer = 0
Dim cellNum As Integer = 0
'Set File Stream
Using doc As WordprocessingDocument = WordprocessingDocument.Open(Stream, True)
'Employee Name Insert
'Find first table in document
Dim tbl1 As Table = doc.MainDocumentPart.Document.Body.Elements(Of Table).First()
'First Row in tbl
Dim row As TableRow = tbl1.Elements(Of TableRow)().ElementAt(0)
'Find first cell in row
Dim cell As TableCell = row.Elements(Of TableCell)().ElementAt(0)
'Insert selected Employee Name
Dim p As Paragraph = cell.Elements(Of Paragraph)().First()
Dim r As Run = p.Elements(Of Run)().First()
Dim txt As Text = r.Elements(Of Text)().First()
txt.Text = "Employee Name: " & ddlEmployeeList.SelectedItem.Text
'Supervisor Name Insert
'Check for form
If ddlFormChoice.SelectedIndex <> 2 Then
'Reset row to supervisors row in table
row = tbl1.Elements(Of TableRow)().ElementAt(1)
ElseIf ddlFormChoice.SelectedIndex = 2 Then
'Reset row to supervisors row in table
row = tbl1.Elements(Of TableRow)().ElementAt(2)
End If
If ddlFormChoice.SelectedIndex <> 2 Then
'Reset cell to supervisor cell in row
cell = row.Elements(Of TableCell)().ElementAt(1)
ElseIf ddlFormChoice.SelectedIndex = 2 Then
'Reset cell to supervisor cell in row
cell = row.Elements(Of TableCell)().ElementAt(0)
End If
'Insert selected Employee Name
p = cell.Elements(Of Paragraph)().First()
r = p.Elements(Of Run)().First()
txt = r.Elements(Of Text)().First()
If ddlFormChoice.SelectedIndex <> 2 Then
txt.Text = "Supervisor: " & ddlSupervisorList.SelectedItem.Text
ElseIf ddlFormChoice.SelectedIndex = 2 Then
txt.Text = "Manager/Supervisor: " & ddlSupervisorList.SelectedItem.Text
End If
doc.Close()
End Using
'Save File to temp location
File.WriteAllBytes("\\WEB-DEV-1\HR_Documents\TempDocs\" & worddoc, Stream.ToArray())
Stream.Close()
Stream.Dispose()
Return 1
Catch ex As Exception
Return Nothing
End Try
End Using
End Function
I close the OpenXML doc and the stream as well dispose of the stream but when I try to delete the file from the main sub that called the function I get the error listed above.
What am I missing?? I closed the doc, the stream and disposed of the stream. Why is the site still holding the file?
Note here the line of code that trys to delete the file;
File.Delete("\\Web-Dev-1\HR_Documents\TempDocs\" & fileAttach)
So after most of the day i finally found out what the problem was. After the document was created, saved , and emailed it was being held by the email method. For some reason i thought that when the method finishes that it disposed of the Mail Message but this not the case.
Once I added the dispose line it all worked fine.
Only been Googling for almost two days. :|
i'm new to vb.net, and i want to open an existing excel file, and insert an image to a specific cell, such as 'C16' for exemple.
It's been three days and i'm searching about this topic, but what i found was just creating a new excel file and insert a picture to it.
Anybody can help?
The code can be used is like this:
ActiveSheet.Pictures.Insert(pathForPicture & "\" & pictureName & ".jpg").Select 'Path to where pictures are stored
For more reading from this site: VBA to insert embeded picture excel
How to insert a picture into Excel at a specified cell position with VBA
I've already found a solution:
please find it below
workbook = APP.Workbooks.Open(filepath)
worksheet = workbook.Worksheets("name of the excel sheet")
worksheet.Visible = True
Dim pic1 As String = "picture path"
worksheet.Range("I51:I51").Select()
I51 is the cell where i want my picture
worksheet.PageSetup.Zoom = False
worksheet.PageSetup.FitToPagesWide = 1
worksheet.PageSetup.FitToPagesTall = 1
Dim opicture1 As Object
opicture1 = worksheet.Pictures.Insert(pic1)
I would like to provide my codes.
Dim picPath As String = "C:\..."
Dim _Left = xlWorkSheet.Range(WorkSheet.Cells(i, j).Address).Left
Dim _Top = xlWorkSheet.Range(WorkSheet.Cells(i, j).Address).Top
Dim _Width = xlWorkSheet.Range(WorkSheet.Cells(i, j).Address).Width
Dim _Height = xlWorkSheet.Range(WorkSheet.Cells(i, j).Address).Height
WorkSheet.Shapes.AddPicture(picPath, False, True, _Left, _Top, _Width, _Height)
picPath is the path of the image you want to insert.
(i,j) is the index of the cell where you want to insert an image.
I'm trying to copy all the elements from a word doc to a new word doc. When I try to get all ChildElements I get the message "Object reference not set to an instance of an object" on this line "For Each element As OpenXmlElement In templatedoc.MainDocumentPart.Document.Body.ChildElements"
Please help
Code:
Dim containerElement = NewDocument.MainDocumentPart.Document.Descendants().FirstOrDefault()
Dim clonedElements = New List(Of OpenXmlElement)
For Each element As OpenXmlElement In templatedoc.MainDocumentPart.Document.Body.ChildElements
clonedElements.Add(element.Clone())
Next
containerElement.RemoveAllChildren()
containerElement.Append(clonedElements)
Thanks guys and girls!
Here is my final working code:
' Copy XML parts to define document
NewDocument.AddPart(templatedoc.GetPartById("rId3"), "rId3")
NewDocument.AddPart(templatedoc.GetPartById("rId2"), "rId2")
'// Add a main document part.
Dim mainPart = NewDocument.AddMainDocumentPart()
' // Add a Body
mainPart.Document = New Document(New Body())
'Copy Document XMLParts - must be in specific order
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId8"), "rId8")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId3"), "rId3")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId7"), "rId7")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId2"), "rId2")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId1"), "rId1")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId6"), "rId6")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId5"), "rId5")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId4"), "rId4")
mainPart.AddPart(templatedoc.MainDocumentPart.GetPartById("rId9"), "rId9")
'// Copy text from template document
Dim containerElement = NewDocument.MainDocumentPart.Document.Descendants().FirstOrDefault()
Dim clonedElements = New List(Of OpenXmlElement)
Dim elementstocopy = templatedoc.MainDocumentPart.Document.Body.ChildElements
For Each element As OpenXmlElement In elementstocopy
clonedElements.Add(element.Clone())
Next
containerElement.RemoveAllChildren()
containerElement.Append(clonedElements)
mainPart.Document.Save()
I have a form that allows a user to import a spreadsheet. This spreadsheet is generally static when it comes to column headers, but now the users want to be able to include an optional column (called Notes). My code crashes when I try to read the column from the spreadsheet if it doesn't exist.
Dim objCommand As New OleDbCommand()
objCommand = ExcelConnection() 'function that opens spreadsheet and returns objCommand
Dim reader As OleDbDataReader
reader = objCommand.ExecuteReader()
While reader.Read()
Dim Employee As String = Convert.ToString(reader("User"))
Dim SerialNUM As String = Convert.ToString(reader("serialno"))
**Dim Notes As String = Convert.ToString(reader("notes"))**
If the spreadsheet contains a Notes column, all goes well. If not, crash. How can I check to see if the Notes column exists in the spreadsheet to avoid the crash?
Change the code to something like this:
[EDIT - changed code logic)
Dim fieldCount = reader.FieldCount
For i = 0 To fieldCount - 1
Dim colName = reader.GetName(i)
If (colName = "notes") Then
Dim Notes As String = reader.GetString(i)
End If
Next i
Perhaps OleDbDataReader.FieldCount could help you program a workaround.