Prompting for a folder in SSIS 2008 Script Task - vb.net

What I'm trying to do here would seem to be pretty simple. At the start of my SSIS package I want to set a variable to a directory that the user is prompted for. Here's my VB code:
Public Sub Main()
Dim fldDialog As FolderBrowserDialog = New FolderBrowserDialog
fldDialog.Description = "Select the folder..."
fldDialog.ShowNewFolderButton = False
fldDialog.RootFolder = Environment.SpecialFolder.MyDocuments
If fldDialog.ShowDialog() = DialogResult.OK Then
Dts.Variables("variable").Value = fldDialog.SelectedPath
Dts.TaskResult = ScriptResults.Success
Else
MsgBox("You need to select a folder!", MsgBoxStyle.Exclamation, "Error!")
Dts.TaskResult = ScriptResults.Failure
End If
End Sub
Of course, I've got "variable" set as a "ReadWriteVariables" in the Script Task Editor, and the "Imports System.Windows.Forms" at the top of my VB file.
When I run the task it just sits there yellow (as if it's running), but never shows the dialog. There's never even an error, it just sits there. I can run the same code within a standard windows application project no problem.
Not sure what's going on here. On know one quirk of showing an OpenFileDialog is you have to set the ShowHelp property to True, so I'm wondering if there's another quirk to getting this to run. Google only mostly shows me an old problem where the folder tree is blank, but I'm not even getting the prompt. Any help would be much appreciated.

I know it's a little bit late but I came across this Problem and found a fix for this. (Using C#)
You need to use the "OpenFileDialog" instead of the "FolderBrowserDialog" and you need to set a few adjustments. Here is a sample code which opens the explorer and lets you pick a folder:
public void Main()
{
string myPath="";
OpenFileDialog folderBrowser = new OpenFileDialog();
folderBrowser.ValidateNames = false;
folderBrowser.CheckFileExists = false;
folderBrowser.CheckPathExists = true;
folderBrowser.FileName = "Folder Selection.";
folderBrowser.ShowHelp = true;
if (folderBrowser.ShowDialog() == DialogResult.OK)
{
myPath = Path.GetDirectoryName(folderBrowser.FileName);
}
else
{
MessageBox.Show("Error selecting path");
}
Dts.Variables["User::varFolderPath"].Value = myPath;
Dts.TaskResult = (int)ScriptResults.Success;
}
The most important statement is the "folderBrowser.ShowHelp = true" statement. If this assignment isn't made you'll get the same problem as in your question.
You also need the statements above to "trick" the Dialog so you can select a Folder instead of a File.
I hope I can help you or people with the same problem but you should pass in the folder as a variable into the package as "N West" said.

Related

Cannot mark Excel workbook as Final

The situation is as follows:
We want to publish to a remote machine a locally edited file. This file could be of type Word, Excel, Powerpoint. Apparently, after the publishing to the remote machine, we would like the local document to be marked as final, in order to prevent the user from editing it again (, because the intented workflow is first downloading it from the remote server, editing the downloaded document and the publishing it back to the server).
So, there is a bunch of code like this:
Public Sub setDocFinal()
Select Case addin.HostType
Case ADXOfficeHostApp.ohaWord
Dim doc As Word.Document = Nothing
Try
doc = addin.WordApp.ActiveDocument
doc.Final = True
Catch ex As Exception
Throw New Exception(Me.addin.getLabel("cannotSaveCopy", "Cannot Save the document."))
Finally
Marshal.ReleaseComObject(doc)
End Try
Case ADXOfficeHostApp.ohaExcel
Dim doc As Excel.Workbook = Nothing
Try
doc = addin.ExcelApp.ActiveWorkbook
doc.Final = True
'doc.RefreshAll()
'doc.CalculateUntilAsyncQueriesDone()
'doc.Calculate()
Catch ex As Exception
Throw New Exception(Me.addin.getLabel("cannotSaveCopy", "Cannot Save the document."))
Finally
Marshal.ReleaseComObject(doc)
End Try
' Powerpoint case intentionally skipped as is has same format/code
End Select
End Sub
The above code works pretty well for the Word case, but when it comes to Excel, it stacks on the popup which informs the user for the publish action to the remote server:
EDIT
At that particular point, the execution freezes (or maybe gets into an infinite internal loop, because the only available buttons in debugging mode are pause and stop) at the line of setting the document as final and it never reaches the finally statement (where we release the object). It also seems like the execution tries to return control back to the excel document, but nothing more than this notification occurs :
Any idea of what is wrong in the above code, regarding the handling of Excel?
The lines in comments display some trials I have been going through, while trying to find a solution around the net.
In addition, here is also the popup's related code:
Private Sub doWork(ByVal action As String, ByVal e As System.ComponentModel.DoWorkEventArgs)
Dim myDoc As MyDocument
myDoc = DirectCast(e.Argument, MyDocument)
System.Diagnostics.Debug.WriteLine("Post in Thread")
Dim resultObject(3) As Object
resultObject(0) = True
resultObject(1) = myDoc
Dim saveDocumentResult As SaveDocumentResult = Nothing
Try
Select Case action
Case Constants.SAVE_DRAFT
saveDocumentResult = myDoc.getRequestService().saveDraft(myDoc.getSaveFile(), myDoc.getDocName(), myDoc)
Case Constants.PUBLISH
saveDocumentResult = myDoc.getRequestService().publishDocument(myDoc.getSaveFile(), myDoc.getDocName(), myDoc)
myDoc.setDocFinal() 'this line makes the call to the above code
End Select
myDoc.updateDocumentProperty(Constants.VERSION, saveDocumentResult.version)
myDoc.updateDocumentProperty(Constants.HASH, saveDocumentResult.hash)
myDoc.setSaved(True)
System.Threading.Thread.Sleep(1500)
Catch ex As Exception
resultObject(0) = False
resultObject(2) = ex.Message
Finally
e.Result = resultObject
End Try
End Sub

XML Reader Variables VB.NET

Working on a management program for basic files and text.
Now, so far the program is saving information from multiple textboxes into an .xml file correctly.
My problem is where I need to load saved files back into Textboxes.
Here is another thread I made to Microsoft explaining my issue;
Right, so the code I currently have and use;
Private Sub Objectlist1_ItemActivate(sender As Object, e As EventArgs) Handles Objectlist1.ItemActivate
Caseworker.Show()
Me.Objectlist1.MultiSelect = False
Dim selectedListViewItem As String
selectedListViewItem = Me.Objectlist1.SelectedItems.Item(0).ToString
If (IO.File.Exists(selectedListViewItem + "C:\Users\USER\Desktop\Testfolder-data")) Then
Dim document As XmlReader = New XmlTextReader(selectedListViewItem + "C:\Users\USER\Desktop\Testfolder-data")
While (document.Read())
Dim type = document.NodeType
If (type = XmlNodeType.Element) Then
If (document.Name = "Person") Then
Caseworker.Pholderbox.Text = document.ReadInnerXml.ToString()
End If
If (document.Name = "Driver") Then
Caseworker.Driverbox.Text = document.ReadInnerXml.ToString()
Problem here is that I want to be able to click a file in the Listview called "Objectlist1" and the program loads the xml file - Instead of directing the program to One file
As such
If (IO.File.Exists("MyXML.xml")) Then
Dim document As XmlReader = New XmlTextReader("MyXML.xml)
Apparently there is this variable out there that would be perfect for my issue, but I have looked for it for 2 working days and not been able to track it down.
If there is another stuff I need to add to make this thing work, I appreciate any help you can provide.
Am I far off here guys?
A few things:
You need the full path to the XMLFile, not just its name. You could do it like this (warning: untested):
const string basepath= #"C:\Users\USER\Desktop\Testfolder-data"
xmlpath = IO.Path.Combine(basepath, Objectlist1.SelectedItems.Item(0).Text)
If(IO.File.Exists(xmlpath))
Instead of multiple Ifs, I would recommend
switch(document.Name)
{
Case "Person":
Caseworker.Pholderbox.Text=...
break;
Case "Driver":
...
}
If you rename "Pholderbox" to "Personbox", you could spare the entire If/switch and simply do something like:
var textbox = document.name + "box";
(TextBox)Caseworker.Controls[textbox].Text=document.InnerText;
Hope this gets you going.

SaveAs2 method still prompts! Why?

Context:
Vb.net program
Visual studio 2010 ultimate
MS Word 2010 automation
Microsoft.Office.Interop.Word library
I'm using the saveAs2 method to save a new document I'm creating but the application is still prompting me when I call the method. Why?
The application is not visible.
The application.displayAlerts is false
Any ideas guys?
Also, when I do complete the SaveUI prompt by hand, the saveAs2 method throws an exception.
Here's my code for people who asked for it :
Public Sub generateModel() Implements ModelGenerator.generateModel
wordApp.Visible = True
wordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone
wordDoc = wordApp.Documents.Add
wordDoc.PageSetup.TopMargin = wordApp.InchesToPoints(0.25)
wordDoc.PageSetup.BottomMargin = wordApp.InchesToPoints(0.25)
wordDoc.PageSetup.LeftMargin = wordApp.InchesToPoints(0.25)
wordDoc.PageSetup.RightMargin = wordApp.InchesToPoints(0.25)
With wordDoc.Content.Paragraphs.Add(wordDoc.Bookmarks.Item("\endofdoc").Range)
.Range.Text = _text
.Format.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter
.Format.LineUnitBefore = 1
.Range.Font.SmallCaps = True
.Range.Font.Size = 12
End With
Dim logo = wordDoc.Shapes.AddPicture(logoLoc)
logo.Height = wordApp.InchesToPoints(0.5)
logo.Width = wordApp.InchesToPoints(1.18)
Me.mainTable = wordDoc.Tables.Add(wordDoc.Bookmarks.Item("\endofdoc").Range, 3, 2)
mainTable.Rows.HeightRule = Word.WdRowHeightRule.wdRowHeightExactly
mainTable.Columns.Width = wordApp.InchesToPoints(4)
mainTable.Rows.Height = wordApp.InchesToPoints(3.25)
mainTable.Select()
wordApp.Selection.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphLeft
With wordDoc.Content.Paragraphs.Add(wordDoc.Bookmarks.Item("\endofdoc").Range)
.Range.Text = "Rapport journalier de production - page 2"
.Range.Font.Size = 10
.Format.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter
.Format.LineUnitBefore = 0
.Format.SpaceBeforeAuto = False
.Format.SpaceBefore = 0
End With
wordDoc.SaveAs2("C:\Doc1.docx")
wordDoc.Close(False)
wordApp.Application.Quit()
End Sub
**Update:
I tested the code on an other machine and it works. So I tried this code on mine:
Dim app As New Microsoft.Office.Interop.Word.Application
Dim doc = app.Documents.Add
doc.SaveAs2("C:\Users\simon\Documents\Doc3.docx")
And it still makes the saveUI pop up. I'm so confused...
Finally found the problem's source.
My Acer computer was installing an Add-in everytime I installed Word. Once I removed the Add-in from Word everything went back to normal.
The Add-in was the AcerCloud Add-in.
I just tried to create a sample implementation in C#, Word Interop API v.15 (Office 2013):
var wordApplication = new Application() { Visible = true };
var doc = wordApplication.Documents.Add();
doc.SaveAs2(#"C:\my.docx");
... and when you save to a location that requires admin permission (like on the root of the C:\ drive), Word Interop throws a System.Runtime.InteropServices.COMException saying that: "Word cannot save or create this file. Make sure that the disk you want to save the file on is not full, write-protected, or damaged."
Instead, you should save at a location where your application has the necessary write permissions, e.g., to your own user directory - then it should work as expected.

Determine if file is empty (SSIS)

I am trying to develop a package in SSIS 2005 and part of my process is to check if a file on the network is empty or not. If it is not empty, I need to pass a status of successful, otherwise, I need to pass a status of unsuccessful. I think I need a script task, but am not sure how to go about it. Any help is appreciated.
Create a connection to the flat file in the Connection Managers panel.
Under the Control flow tab, add a Data Flow Task.
Double click the Data flow task and add a Flat File Source and Row Count item.
In the Row Count properties, create a RowCount variable.
In the Control Flow tab, create control flow connections based on the result of the #RowCount.
There are two ways to do it:
If file empty means size = 0 you can create a Script Task to do the check:
http://msdn.microsoft.com/en-us/library/ms345166.aspx
If My.Computer.FileSystem.FileExists("c:\myfile.txt") Then
Dim myFileInfo As System.IO.FileInfo
myFileInfo = My.Computer.FileSystem.GetFileInfo("c:\myfile.txt")
If myFileInfo.Length = 0 Then
Dts.Variables["Status"].Value = 0
End If
End If
Otherwise, if file empty means no rows (flat file) you can use the a Row Count transformation after you reads the file. You can set a variable from the Row Count using the 'VariableName' property in Row Count editor and use it as a status.
Add a simple Script Task with the following code(C#) should do the trick:
String FilePath = (string)Dts.Variables["User::FilePath"].Value;
var length = new System.IO.FileInfo(FilePath).Length;
if (length == 0)
Dts.TaskResult = (int)ScriptResults.Success;
else
Dts.TaskResult = (int)ScriptResults.Failure;
This option will run a lot quicker than the accepted answer as it doesn't need to read the whole file, if you are cycling through a folder of files and some of them are large, in my case ~800mb, the accepted answer would take ages to run, this solution runs in seconds.
Yes, a Script task will do the job here. Add a using System.IO statement to the top of the script, then something along the lines of the following in the Main method will check the contents of the file.
public void Main()
{
String FilePath = Dts.Variables["User::FilePath"].Value.ToString();
String strContents;
StreamReader sReader;
sReader = File.OpenText(FilePath);
strContents = sReader.ReadToEnd();
sReader.Close();
if (strContents.Length==0)
MessageBox.Show("Empty file");
Dts.TaskResult = (int)ScriptResults.Success;
}
Edit: VB.Net version for 2005...
Public Sub Main()
Dim FilePath As String = Dts.Variables("User::FilePath").Value.ToString()
Dim strContents As String
Dim sReader As StreamReader
sReader = File.OpenText(FilePath)
strContents = sReader.ReadToEnd()
sReader.Close()
If strContents.Length = 0 Then
MessageBox.Show("Empty file")
End If
Dts.TaskResult = ScriptResults.Success
End Sub

Programmatically save as PowerPoint 2007 (pptx), from PowerPoint 2003

I need to be able to save Presentations (programatically) in PowerPoint 2003 as OpenXML (".pptx").
I installed the Microsoft Office Compatibility Pack. This indeed allows me to perform "Save as PowerPoint 2007 Presentation" from PowerPoint 2003.
How can I do this programmatically? (e.g. VBA)
I tried Presentation.SaveAs:
While there is no inherent PpSaveAsFileType enum value in PowerPoint 2003 for ppSaveAsOpenXMLPresentation, I made a program which prints the PpSaveAsFileType values and found out that during run-time, ppSaveAsOpenXMLPresentation = 24.
However, I tried:
SaveAs(#"c:\temp\saveas\pupik.pptx", (PpSaveAsFileType) ((int) 24), MsoTriState.msoTrue);
And got an "Invalid Enumeration Value" Exception
Any ideas how to make this work?
(PS - I am aware that this question was already asked by several people on the web, but no solutions were offered.)
Thanks,
Arie
Edit > Some grammar
AFAIK the pptx format does not support macro-enabled presentations, so if your code is in the presentation you are trying to save, it will not work.
I don't have Excel 2003 at hand now, but if the Compatibility Pack enabled the option "pptx" in the Configuration Dialog, Default Save Format, and you are trying to save ANOTHER presentation I guess you can if you use something like:
MyOtherPresentation.SaveAs "C:\Mypres", ppSaveAsDefault
Please note that this may work only if the presentation had not been saved before in ppt format
EDIT
If the above doesn't work, you could try a different approach. Save the file in the old format and the call a conversion program:
ppcnvcom.exe
See here for an example (using wordconv.exe, but essentially the same)
Be sure to have all the office upgrades installed, because if not the program ends
reporting no error and doing nothing.
ofc
See here for instructions
And here for a good discussion
HTH!
A trick is to modify the default save format of the application in the Registry, then save and finally to restore the original save format again.
The relevant key is
Software\Microsoft\Office\11.0\PowerPoint\Options
Create a DWORD value with name DefaultFormat and set it to 0x21 to save as PPTX.
public void SomeMethod()
{
...
using (PptxSaver pptxSaver = new PptxSaver())
{
presentation.SaveAs("sample.pptx")
}
...
}
class PptxSaver : IDisposable
{
private const string OptionKey = #"Software\Microsoft\Office\11.0\PowerPoint\Options";
private const string OptionValue = "DefaultFormat";
private const int SaveFormatPptx = 0x21;
private int oldFormat;
public PptxSaver()
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(OptionKey, true))
{
oldFormat = (int)key.GetValue(OptionValue, -1);
key.SetValue(OptionValue, SaveFormatPptx, RegistryValueKind.DWord);
}
}
public void Dispose()
{
// Delete the value
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(OptionKey, true))
{
if (oldFormat == -1)
{
key.DeleteValue(OptionValue);
}
else
{
key.SetValue(OptionValue, oldFormat);
}
}
}
}
I used ppcnvcom.exe but note that unlike a considerable amount of posts I used only the -oice switch without the -nme switch
For VBA this works:
Sub TestSaveas()
SaveAs "c:\somefilepath\"
End sub
Private Sub SaveAs(fp As String)
Dim dlgSaveAs As FileDialog
Dim strMyFile As String
Set dlgSaveAs = Application.FileDialog(msoFileDialogSaveAs)
With dlgSaveAs
.InitialFileName = fp
If .Show = -1 Then
strMyFile = .SelectedItems(1)
Application.ActivePresentation.SaveAs strMyFile
'MsgBox strMyFile
''-- save your file to strMyFile here
Else
MsgBox "File not saved"
End If
End With
dlgSaveAs.Execute
Set dlgSaveAs = Nothing
End Sub
I know this is an old question, but I got around the problem recently using:
Presentation.SaveCopyAs "c:\temp\saveas\pupik.pptx"
instead of SaveAs. Works well, regardless wether the original is in ppt- or pptx-format.
(I could not get the registry-change method mentioned to work for me without reopening the presentation.)