Excel doc contents to webservice - wpf

I have a wpf staff creation window in which I can create basic information like first name, last name etc this creates the staff in my REST web service. An example:
Client side:
private void CreateStaffMember_Click(object sender, RoutedEventArgs e)
{
string uri = "http://localhost:8001/Service/Staff";
StringBuilder sb = new StringBuilder();
sb.Append("<Staff>");
sb.AppendLine("<FirstName>" + this.textBox1.Text + "</FirstName>");
sb.AppendLine("<LastName>" + this.textBox2.Text + "</LastName>");
sb.AppendLine("<Password>" + this.passwordBox1.Password + "</Password>");
sb.AppendLine("</Staff>");
string NewStudent = sb.ToString();
byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "application/xml";
req.ContentLength = arr.Length;
Stream reqStrm = req.GetRequestStream();
reqStrm.Write(arr, 0, arr.Length);
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
MessageBox.Show("Staff Creation: Status " + resp.StatusDescription);
reqStrm.Close();
resp.Close();
}
Web Service side:
#region POST
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/Staff")]
void AddStaff(Staff staff);
#endregion
public void AddStaff(Staff staff)
{
staff.StaffID = (++eCount).ToString();
staff.Salt = GenerateSalt();
byte[] passwordHash = Hash(staff.Password, staff.Salt);
staff.Password = Convert.ToBase64String(passwordHash);
staffmembers.Add(staff);
}
All fine on that side, but Im looking to "import" the staff details from an excel spreadsheet, not sure if import is the correct word but I want to take the first names and last names contained in such n such spreadsheet and add them to the web service from the client side wpf application.
How would I go about it? I have my open file dialog:
private void Import_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
}
}
So I open my excel spread sheet then how would I go about taking the inner contents and sending it to the web service? Really stuck on the code or how to go about it :/
Just looking for an automated way of adding staff members rather than manually typing the names, but seeing as the staff excel doc could be named anything I wanted the open file dialog box. The structure inside will always be the same first name then last name.

First, here is my test Excel file that contains the Staff you want to import:
(Column 'A' if first name, column 'B' is last name and column 'C' is the password...)
Ok, so assuming that your code calling your web service works, here is my version of the Import_Click method (and a generic method to save new staff):
private void Import_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
Microsoft.Office.Interop.Excel.Application vExcelObj = new Microsoft.Office.Interop.Excel.Application();
try
{
Workbook theWorkbook = vExcelObj.Workbooks.Open(filename, Type.Missing, true);
Worksheet sheet = theWorkbook.Worksheets[1]; // This is assuming that the list of staff is in the first worksheet
string vFirstName = "temp";
string vLastName = "temp";
string vPassword = "temp";
int vIndex = 1;
while (vFirstName != "")
{
// Change the letters of the appropriate columns here!
// In my example, 'A' is first name, 'B' is last name and 'C' is the password
vFirstName = sheet.get_Range("A" + vIndex.ToString()).Value.ToString();
vLastName = sheet.get_Range("B" + vIndex.ToString()).Value.ToString();
vPassword = sheet.get_Range("C" + vIndex.ToString()).Value.ToString();
this.SaveNewStaff(vFirstName, vLastName, vPassword);
vIndex++;
}
}
catch (Exception ex)
{
MessageBox.Show("Error processing excel file : " + ex.Message);
}
finally {
vExcelObj.Quit();
}
}
}
private void SaveNewStaff(string firstName, string lastName, string password) {
string uri = "http://localhost:8001/Service/Staff";
StringBuilder sb = new StringBuilder();
sb.Append("<Staff>");
sb.AppendLine("<FirstName>" + firstName + "</FirstName>");
sb.AppendLine("<LastName>" + lastName + "</LastName>");
sb.AppendLine("<Password>" + password + "</Password>");
sb.AppendLine("</Staff>");
string NewStudent = sb.ToString();
byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "application/xml";
req.ContentLength = arr.Length;
Stream reqStrm = req.GetRequestStream();
reqStrm.Write(arr, 0, arr.Length);
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
//MessageBox.Show("Staff Creation: Status " + resp.StatusDescription);
reqStrm.Close();
resp.Close();
}
Note: I have REMed out the MessageBox in the call to the web service to make sure you are not annoyed by it if the list is long, but you are free to "unREM" it if you need confirmation for every staff creation. In the same line of taught, there is not validation that the creation has occurred successfully. I would need more details to create a decent validation process.
Also VERY important, this does not validate if the staff you are saving already exists in the list. If you re-run this import procedure multiple times, it may (and probably will) create duplicate entries.
Cheers

Related

SSIS - Sending email different recipients different data

I'm new in SSIS.
I have a table with 1500 rows and I need to send emails from that table but each recipients has 15 rows from the table.
So I need to send different data to different emails from the same query.
Can you guys could help me please?
Thanks in advance.
Leo
-------------------update------------------------
Guys I could create a SSIS package to send email to different recipients the problem is: sample: 2 different users is receiving emails for the number of rows that they have in database...that's terrible each customer has 15 lines it will be 15 emails can I send just one email for customer contains the whole data?
Thanks in advance...
This is going to vary somewhat based on the query and other specifications, but at a high level you're probably going to want to follow these steps for sending the emails using SSIS. This example assumes that the emails are stored in a column within this table. As others have pointed out, using sp_send_dbmail will likely be your best option.
Create two string variables. One will hold the email addresses and the other will be for the SQL for sp_send_dbmail (more on this below). Create an additional variable of the object type that will hold the list of emails during execution.
Modify the string variable that will hold the SQL for sp_send_dbmail to be an expression using the variable with the email names. Depending on the query, you may need to add additional variables for other parameters in this query. An example of this variable is at the end of this post.
Have an initial Execute SQL Task that queries the table and retrieves the email addresses. Make sure to get all rows for each email. Set the ResultSet property to full and on the Result Set pane, add the object variable with 0 as the Result Name.
Next add a Foreach Loop, use the Foreach ADO Enumerator type, and select the object variable from the last Execute SQL Task for the source variable. The Enumeration Mode can be left as the "Rows in the first table" option.
On the Variable Mappings pane, add the string variable (for the email addresses) and set the index to 0. This will hold the email addresses for each execution of sp_send_dbmail.
Within the Foreach Loop, add an Execute SQL Task. For this, you will need to set the SQLSourceType to variable and use a variable holding the SQL with sp_send_dbmail.
Make sure that you have Database Mail properly configured for the account and profile used, including membership in the DatabaseMailUserRole role in msdb. You may also need to use the three-part name (database.schema.table) for your table.
Example SQL Variable Expression:
Note the double-quotes in the #query parameter around the email variable in addition to the quotes from concatenating the expression. You can either use two single quotes or precede a double-quote with a \ in the query to use a double-quote as part of the expression.
"DECLARE #Title varchar(100)
SET #Title = 'Email Title'
EXEC MSDB.DBO.SP_SEND_DBMAIL #profile_name = 'Your Profile',
#recipients = 'YourEmail#test.org',
#query = 'SELECT * FROM YourDatabase.YourSchema.YourTable WHERE EmailColumn = ""
+ #[User::VariableWithEmailAddress] + ""',
#query_result_no_padding = 1, #subject = #Title ; "
I have a package that sole role is to send emails from my packages and record the results in to a table. I use this package over and over from any package that sends mail.
It is simply a script task, that takes parameters and does the work:
The script to process:
public void Main()
{
//Read variables
#region ReadVariables
string cstr = Dts.Variables["connString"].Value.ToString();
//string sender = (string)Dts.Variables["User::Sender"].Value;
string title = (string)Dts.Variables["$Package::Title"].Value;
string priority = (string)Dts.Variables["$Package::Priority"].Value;
string body = (string)Dts.Variables["$Package::Body"].Value;
string source = Dts.Variables["$Package::Source"].Value.ToString();
string directTo = Dts.Variables["$Package::DirectMail"].Value.ToString();
string groups = Dts.Variables["$Package::MailGroups"].Value.ToString();
#endregion
//Send Email
#region SendMail
MailMessage mail = new MailMessage();
//mail.From = new MailAddress(sender);
mail.Subject = title;
mail.Body = body;
mail.IsBodyHtml = true;
switch(priority.ToUpper())
{
case "HIGH":
mail.Priority= MailPriority.High;
priority = "High";
break;
default:
mail.Priority=MailPriority.Normal;
priority = "Normal";
break;
}
DataTable dt = new DataTable(); //This is going to be a full distribution list
//Fill table with group email
if (groups.Split(',').Length > 0)
{
foreach (string group in groups.Split(','))
{
string strCmd = "mail.spGetEmailAddressesByGroup";
using (OleDbConnection conn = new OleDbConnection(cstr))
{
using (OleDbCommand cmd = new OleDbCommand(strCmd, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("A", group);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
}
}
}
}
//add the directs to email
if (directTo.Split(',').Length > 0)
{
foreach (string m in directTo.Split(','))
{
if (m != "")
{
DataRow dr = dt.NewRow();
dr[0] = "TO";
dr[1] = m;
dt.Rows.Add(dr);
}
}
}
//Add from and reply to defaults
DataRow dr2 = dt.NewRow();
dr2[0] = "REPLYTO";
dr2[1] = ""; //WHERE DO YOU WANT REPLIES
dt.Rows.Add(dr2);
DataRow dr3 = dt.NewRow();
dr3[0] = "FROM";
dr3[1] = ""; //ENTER WHO YOU WANT THE EMAIL TO COME FROM
dt.Rows.Add(dr3);
//Bind dt to mail
foreach (DataRow dr in dt.Rows)
{
switch (dr[0].ToString().ToUpper())
{
case "TO":
mail.To.Add(new MailAddress(dr[1].ToString()));
dr[0] = "To";
break;
case "CC":
mail.CC.Add(new MailAddress(dr[1].ToString()));
dr[0] = "Cc";
break;
case "BCC":
mail.Bcc.Add(new MailAddress(dr[1].ToString()));
dr[0] = "Bcc";
break;
case "REPLYTO":
mail.ReplyToList.Add(new MailAddress(dr[1].ToString()));
dr[0] = "ReplyTo";
break;
case "FROM":
mail.From = new MailAddress(dr[1].ToString());
dr[0] = "From";
break;
case "SENDER":
mail.Sender = new MailAddress(dr[1].ToString());
dr[0] = "Sender";
break;
default:
dr[0] = "NotSent";
break;
}
}
try
{
SmtpClient smtp = new SmtpClient();
smtp.Port = 25;
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.UseDefaultCredentials = false;
smtp.Host = ""; //ENTER YOUR IP / SERVER
smtp.Send(mail);
}
catch (Exception e)
{
}
#endregion
//Record email as sent //I WILL NOT BE PROVIDING THIS PART
//#region RecordEmailInDB
That's just to send mails, I have many packages that build the emails to send. Most are variables to parameters on the call. The most complicated is the building of the Email Body and this is where your specific question comes into play.
This is a sample control flow:
There's a data flow that queries the details that need to be sent and are recorded into an object. As well as a record counter.
Back to control flow. There is a precendence constraint set to rowcount >0.
The I have a script task to build the body basically. And I have a class that converts the ADO Object into an HTML table.
public string BuildHTMLTablefromDataTable(DataTable t)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<table border='1'><tr style='background-color: #1A5276; color:#FFFFFF;'>");
foreach (DataColumn c in t.Columns)
{
sb.Append("<th align='left'>");
sb.Append(c.ColumnName);
sb.Append("</th>");
}
sb.Append("</tr>");
int rc = 0;
foreach (DataRow r in t.Rows)
{
rc++;
//every other row switches from white to gray
string OpeningTR = "<tr style='background-color: " + ((rc % 2 == 1) ? "#E5E7E9;'>" : "#FCF3CF;'>");
sb.Append(OpeningTR);
foreach (DataColumn c in t.Columns)
{
sb.Append("<td align='left'>");
sb.Append(System.Web.HttpUtility.HtmlEncode(
r[c.ColumnName] == null ? String.Empty : r[c.ColumnName].ToString()
)); //This will handle any invalid characcters and convert null to empty string
sb.Append("</td>");
}
sb.Append("</tr>");
}
sb.Append("</table>");
return sb.ToString();
}
public string BuildBody(DataTable dt)
{
string body = "<P>The following are vouchers that are not in the voucher table but in the GL:</p>";
DataView v = new DataView(dt);
body += BuildHTMLTablefromDataTable(dt); //v.ToTable(true, "Name", "LastVisit", "DaysUntilTimeout", "ExpDate", "RoleName"));
return body;
}
public void Main()
{
#region Read Variables
System.Data.OleDb.OleDbDataAdapter da = new System.Data.OleDb.OleDbDataAdapter();
DataTable dt = new DataTable();
da.Fill(dt, Dts.Variables["User::Changes"].Value);
#endregion
string body = BuildBody(dt);
Dts.Variables["User::Body"].Value = body;
Dts.TaskResult = (int)ScriptResults.Success;
}
Finally I will call the SendMail package and pass the parameters.
For your purpose you will need to have a foreach around this package and adjust your where clause for the person on each pass.
This is an example of an email sent (Body only):

Display XPS Document in WPF

I need to display data from a database into a WPF app and save it as an XPS document. I want to display it as part of a main window (with Toolbar, Menu and StatusBar) and not as a new window.
What control(s) should I use? Currently, I am looking at FixedDocument and FlowDocument. Am I on the right track? Any good material on how to start?
Improving on Stehpen's answer above...
Assume you've added a documents folder to your project:
Create a method GetDocument where the GetFilePath method refers to the Folder/Filename in the folder above.
private void GetDocument()
{
string fileName = Environment.CurrentDirectory.GetFilePath("Documents\\Title.xps");
Debugger.Break();
XpsDocument doc = new XpsDocument(fileName, FileAccess.Read);
XDocViewer.Document = doc.GetFixedDocumentSequence();
}
Where GetFilePath is an extension method that looks like this:
public static class StringExtensions
{
public static string GetFilePath(
this string EnvironmentCurrentDirectory, string FolderAndFileName)
{
//Split on path characters
var CurrentDirectory =
EnvironmentCurrentDirectory
.Split("\\".ToArray())
.ToList();
//Get rid of bin/debug (last two folders)
var CurrentDirectoryNoBinDebugFolder =
CurrentDirectory
.Take(CurrentDirectory.Count() - 2)
.ToList();
//Convert list above to array for Join
var JoinableStringArray =
CurrentDirectoryNoBinDebugFolder.ToArray();
//Join and add folder filename passed in
var RejoinedString =
string.Join("\\", JoinableStringArray) + "\\";
var final = RejoinedString + FolderAndFileName;
return final;
}
}
Add a Document viewer in your XAML
And add this code in the cs file:
string fileName = null;
string appPath= System.IO.Path.GetDirectoryName(Assembly.GetAssembly(typeof(DocumentWindow)).CodeBase);
fileName = appPath + #"\Documents\Help.xps";
fileName = fileName.Remove(0, 6);
XpsDocument doc = new XpsDocument(fileName, FileAccess.Read);
docView.Document = doc.GetFixedDocumentSequence();

How to Use a Web Service to Update TextBox controls in ASP.NET?

I have a web form where I need to add, update, delete and read using a unique ID. So far I have managed to add, update and delete functions with little trouble.
However now I am having trouble getting my read function to work (understand I have a webform that has four text fields; ID, FIRSTNAME, SURNAME AND ADDRESS). Basically when an ID that has been previously created (using add button) is entered into the text field and the read button clicked it should update the other 3 text fields with the stored entries depending on the ID entered.
Here is my behind code (cs.) on the web form
protected void cmdRead_Click(object sender, EventArgs e)
{
// Create a reference to the Web service
DbWebService.WebService1 proxy = new DbWebService.WebService1();
// Create a person details object to send to the Web service.
string ADDRESS;
string SURNAME;
string FIRSTNAME;
string ID;
ADDRESS = txtAddress.Text;
SURNAME = txtSurname.Text;
FIRSTNAME = txtFirstname.Text;
ID = txtID.Text;
// Attempt to store in the Web service
bool rsp = proxy.ReadPerson(int.Parse(ID), FIRSTNAME, SURNAME, ADDRESS);
// Inform the user
if (rsp)
{
lblOutcome.Text = "Successfully read data.";
txtFirstname.Text = FIRSTNAME;
txtSurname.Text = SURNAME;
txtAddress.Text = ADDRESS;
}
else
{
lblOutcome.Text = "Failed to read data! Select a previously created ID!";
}
}
and here is my web function on the web service (which is where the SQL Server Express database is)
[WebMethod]
public bool ReadPerson(int ID, string FIRSTNAME, string SURNAME, string ADDRESS)
{
// In case of failure failure first
bool rtn = false;
// Connect to the Database
SqlConnection connection = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename='|DataDirectory|\Database.mdf';Integrated Security=True;User Instance=True");
// Open the connection
connection.Open();
// Prepare an SQL Command
SqlCommand command = new SqlCommand(String.Format("SELECT FIRSTNAME, SURNAME, ADDRESS FROM PersonalDetails WHERE ID = '{0}'", ID), connection);
// Execute the SQL command and get a data reader.
SqlDataReader reader = command.ExecuteReader();
// Instruct the reader to read the first record.
if (reader.Read())
{
// A record exists, thus the return value is updated
FIRSTNAME = (string)reader["FIRSTNAME"];
SURNAME = (string)reader["SURNAME"];
ADDRESS = (string)reader["ADDRESS"];
rtn = true;
}
// Close the connection
connection.Close();
// Return the result.
return (rtn);
}
Now the problem is when I click read I get a success message (using a label as you can see in the behind code) but the fields don't update, I assume this is because of the (rtn = true;) statement. Therefore I thought something like this might work:
rtn = (bool)reader["ADDRESS"];
However with this I get a specified cast is not valid, so I figure maybe the bool doesn't work in this context, I think it might work if I use string instead but how do I convert, I think rtn needs a value in regards to the reader right??
Basically I am just looking for a solution to which will update the text fields in the web form.
There are several problems with your code. The most obvious is that your code cannot ever return the data from the database. You are sending FIRSTNAME etc. to the web service - you are not returning them from the web service.
There is no reason to have a bool return from the service to tell you whether or not it succeeded. Let the service throw an exception if it failed. Instead, you should return the fields from the database as the return of the service.
In the service:
public class Person
{
public string FIRSTNAME {get;set;}
public string SURNAME {get;set;}
public string ADDRESS {get;set;}
}
[WebMethod]
public Person ReadPerson(int ID)
{
// ...
if (reader.Read())
{
// A record exists, thus return the value
Person p = new Person();
p.FIRSTNAME = (string)reader["FIRSTNAME"];
p.SURNAME = (string)reader["SURNAME"];
p.ADDRESS = (string)reader["ADDRESS"];
rtn = p;
}
connection.Close();
return rtn;
}
Also, you should not be using a WebMethod or an ASMX web service unless you have no choice. ASMX is a legacy technology which is kept around only for backwards compatability. It should not be used for new development. You should use WCF instead.
The other issues with your code are resolved below:
[WebMethod]
public Person ReadPerson(int id)
{
using (
var connection =
new SqlConnection(
#"Data Source=.\SQLEXPRESS;
AttachDbFilename='|DataDirectory|\Database.mdf';
Integrated Security=True;
User Instance=True")
)
{
connection.Open();
using (
var command =
new SqlCommand(#"
SELECT FIRSTNAME, SURNAME, ADDRESS
FROM PersonalDetails
WHERE ID = #id",
connection))
{
var idParameter =
command.Parameters.Add(
"#id", SqlDbType.Int);
idParameter.Value = id;
using (var reader = command.ExecuteReader())
{
if (!reader.Read())
{
return null;
}
return new Person
{
Firstname =
(string)
reader["FIRSTNAME"],
Surname =
(string)
reader["SURNAME"],
Address =
(string)
reader["ADDRESS"]
};
}
}
}
}
The main issue is that the SqlConnection, SqlCommand, and SqlDataReader all need to be instantiated inside of using blocks. This ensures that the objects are disposed of (closed) whether or not an exception is thrown.
Next, you should not get into the habit of building queries through string manipulation; not even using String.Format. That leaves you open to "SQL Injection" attacks. Using parameters resolves that problem. See "Commands and Parameters " in MSDN.
One last minor issue: I recommend that you get out of the habit of placing comments on obvious statements. For instance, it's not necessary to comment that Open opens the connection to the database, or that return returns a value.

How to get WPF ListBox Text displayed in the ListBox Window?

I am SIMPLY trying to set an ID Value (using ListBox.SelectedValuePath) to a WPF ListBox and show the assoicated (Date) Text (using ListBox.DisplayMemberPath) in the ListBox Window. The problem is I am unable to GET the Text from the ListBox Window! I have done this numerous times using a ComboBox, but it does not seem to work with a ListBox. The ListBox does not have a ListBox.Text property from which to obtain the Text displayed in the ListBox Window, in this case a date. Here is my code (I am trying to get the Text from the lstBidPeriods Window to populate a second ListBox (lstHolidays) by querying the database for holidays for the date of the selected bid period, from the lstBidPeriods):
private void loadBidPeriods()
{
lstBidPeriods.DisplayMemberPath = "Text";
lstBidPeriods.SelectedValuePath = "Value";
//lstBidPeriods.ItemTemplate.RegisterName(
lstBidPeriods.ItemsSource = func.GetBidPeriods(func.SelectedYear, func.SelectedMonth);
}
private void lstBidPeriods_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
lstHolidays.ItemsSource = null;
DateTime date = DateConversions.MIN_DATE;
Console.WriteLine("SelectedItem= " + lstBidPeriods.SelectedItem.ToString());
Console.WriteLine("SelectedValue= " + lstBidPeriods.SelectedValue.ToString());
Console.WriteLine("Items[index]= " + lstBidPeriods.Items[lstBidPeriods.SelectedIndex].ToString());
if (DateTime.TryParse(lstBidPeriods.SelectedItem.ToString(), out date))
{
Console.WriteLine("BID date: " + date);
lstHolidays.DisplayMemberPath = "Text";
lstHolidays.SelectedValuePath = "Value";
lstHolidays.ItemsSource = func.GetBidPeriodHolidays(date);
}
Console.WriteLine("NOW date: " + date);
}
public ArrayList GetBidPeriods(short selYear, byte selMonth)
{
DataTable periods = new DataTable();
ArrayList list = new ArrayList();
try
{
SqlConnection conn = openNewConnection();
SqlCommand cmd = new SqlCommand("getBidPeriods", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#selMonth", SqlDbType.TinyInt);
cmd.Parameters.Add("#selYear", SqlDbType.SmallInt);
cmd.Parameters["#selMonth"].Value = selMonth;
cmd.Parameters["#selYear"].Value = selYear;
periods = GetDataTable(cmd);
foreach (DataRow row in periods.Rows)
{
DateTime date = new DateTime((short)row["Bid_Year"], (byte)row["Bid_Month"], (byte)row["Bid_Day"]);
list.Add(new ListContent(row["Bid_Id"].ToString(), date.ToShortDateString()));
}
conn.Close(); conn.Dispose(); cmd.Dispose();
}
catch (Exception e)
{
message = "Error Obtaining Bid Periods: " + e.Message.ToString();
FileWizard.writeDate(FileWizard.LOGFILE_DIRECTORY + "appExceptionLog_"
+ DateConversions.GetMonthName(now.Month) + now.Year.ToString() + ".log",
"User: " + GFIFunctions.GFIUser + "\tClass: GFIDBInterface\tFunction: GetBidPeriods"
+ "\tException: " + message);
MessageBox.Show("Notify System Administrator: " + message, "GFI RIDER Application Exception ");
}
return list;
}
public ArrayList GetBidPeriodHolidays(DateTime bidPeriodDateStartingWithDate)
{
DataTable holidays = new DataTable();
ArrayList list = new ArrayList();
try
{
SqlConnection conn = openNewConnection();
SqlCommand cmd = new SqlCommand("getBidPeriodHolidays", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#bidHolidayDatesGreaterThanOrEqualTo", SqlDbType.DateTime);
cmd.Parameters["#bidHolidayDatesGreaterThanOrEqualTo"].Value = bidPeriodDateStartingWithDate;
holidays = GetDataTable(cmd);
foreach (DataRow row in holidays.Rows)
{
list.Add(new ListContent(row["Bid_Holiday_Id"].ToString(), ((DateTime)row["Bid_Holiday_Date"]).ToShortDateString()));
}
conn.Close(); conn.Dispose(); cmd.Dispose();
}
catch (Exception e)
{
message = "Error Obtaining Bid Period Holidays: " + e.Message.ToString();
FileWizard.writeDate(FileWizard.LOGFILE_DIRECTORY + "appExceptionLog_"
+ DateConversions.GetMonthName(now.Month) + now.Year.ToString() + ".log",
"User: " + GFIFunctions.GFIUser + "\tClass: GFIDBInterface\tFunction: GetBidPeriodHolidays"
+ "\tException: " + message);
MessageBox.Show("Notify System Administrator: " + message, "GFI RIDER Application Exception ");
}
return list;
}
PLEASE: I do not need to BIND anything, so don't go there. This SHOULD be a SIMPLE procedure, not anything complicated with UNECESSARY binding.
Allow me to explain a few of the things you are doing in your code, and the answer will be crystal clear.
You are provided a list of "ListContent" objects to the listbox.
lstBidPeriods.DisplayMemberPath = "Text";
lstBidPeriods.ItemsSource = func.GetBidPeriods(....
So, I assume that you have a public property in the ListContent class called "Text". If so, then your list will show up, listing the ids of your BidPeriods. Great.
But you also specified this:
lstBidPeriods.SelectedValuePath = "Value";
By doing that you change how the selection works a little bit. Lets take a look at the various selection properties.
lstBidPeriods.SelectedItem - Returns the actual ListContent instance that is selected, because remember you passed a list of ListContent instances.
lstBidPeriods.SelectedValue - Returns the "Value" property of the selected ListContent instance - so this is the date string
lstBidPeriods.SelectedIndex - Returns the index of the selected item in the list.
So to get the date string, use the SelectedValue,
if (DateTime.TryParse(lstBidPeriods.SelectedValue.ToString(), out date))
{
...
}
That's it.

Programatically add document to Hummingbird/OpenText eDocs database

I am working with the the (formerly Hummingbird Enterprise) OpenText eDocs document management system.
http://www.opentext.com/2/global/products/products-opentext-edocs-products/products-opentext-edocs-document-management.htm
We are still using Hummingbird 5.1.0.5.
I have been reviewing the API docs for this software, but some areas are slightly vague.
So far, I can create my Profile form, populate some values.
DOCSObjects.Application docApp = null;
DOCSObjects.IProfile profile = null;
Type fType = Type.GetTypeFromProgID("DOCSObjects.Application");
docApp = (DOCSObjects.Application)Activator.CreateInstance(fType);
try { profile = docApp.CurrentLibrary.CreateProfile("DEF_PROF"); }
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); }
if (profile != null)
{
try
{
profile.Columns["DOCNAME"].Value = "New PDF Document";
profile.Columns["APP_ID"].Value = "ACROBAT";
profile.ShowProfile(1);
// not sure how to set a document here
profile.SetDocument(docApp.CurrentLibrary.Name, document);
profile.Save(); // requires a short flag, but what?
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
else
{
MessageBox.Show("Profile is null");
}
Where I am having trouble is how to save a document with the profile.
I am using C# and the API docs and intellisense simply ask for on object for the document.
Does that mean the path or do I need to load the PDF into some specific DOCSObjects type?
Also, the API docs references a Constant such as OF_NORMAL when saving the document. I assume this is 0, but are there others I should know about? There are many Constants referenced in the docs that have no values defined. (All examples are in C++/VB).
I know it's a long shot anyone is using this software, but thought I would give it a try.
Thank you and any assistance is appreciated.
I have done it in VB - using an API wrapper that I created. You should use the PCDClient under DM API folder instead of the DOCSObjects.
This code here probably won't work right away for you because it is heavily customized, but play around with it and you can probably figure it out. Good Luck!
Public Sub CreateProfile(ByRef Doc As Profile)
Try
'SET THE STATIC META DATA
Doc.objDoc.SetProperty("TYPE_ID", "DOCS") ' DOCUMENT TYPE IS ALWAYS DOCS
Doc.objDoc.SetProperty("TYPIST_ID", RDIMSAPI._UserID)
Doc.objDoc.SetProperty("APP_ID", RDIMSData.GetApp(Doc.FileToImport)) ' FILE TO IMPORT
'CREATE THE DOCUMENT
Doc.objDoc.Create()
If Doc.objDoc.ErrNumber <> 0 Then
Throw New Exception(Doc.objDoc.ErrNumber & " - " & Doc.objDoc.ErrDescription)
End If
'RETRIEVE THE NEW DOCUMENT PROFILE
Dim DocNumber As Integer = Doc.objDoc.GetReturnProperty("%OBJECT_IDENTIFIER")
Dim VersionID As Integer = Doc.objDoc.GetReturnProperty("%VERSION_ID")
'ADD THE DOCUMENT TO THE PROFILE
Dim objPutDoc As New PCDClient.PCDPutDoc
objPutDoc.SetDST(RDIMSAPI._sDST)
objPutDoc.AddSearchCriteria("%TARGET_LIBRARY", RDIMSAPI._Library)
objPutDoc.AddSearchCriteria("%DOCUMENT_NUMBER", DocNumber)
objPutDoc.AddSearchCriteria("%VERSION_ID", VersionID)
objPutDoc.Execute()
If objPutDoc.ErrNumber <> 0 Then
Throw New Exception(Doc.objDoc.ErrNumber & " - " & Doc.objDoc.ErrDescription)
End If
objPutDoc.NextRow()
'UPLOAD THE DOCUMENT
Dim objPutStream As PCDClient.PCDPutStream = objPutDoc.GetPropertyValue("%CONTENT")
Dim fs As FileStream = System.IO.File.OpenRead(Doc.FileToImport)
Dim fi As FileInfo = New System.IO.FileInfo(Doc.FileToImport)
Dim br As BinaryReader = New BinaryReader(fs)
Dim addDocBytes As Byte() = br.ReadBytes(CInt(fs.Length))
br.Read(addDocBytes, 0, addDocBytes.Length)
br.Close()
Dim bytesWritten As Integer = 0
objPutStream.Write(addDocBytes, addDocBytes.Length, bytesWritten)
objPutStream.SetComplete()
'UNLOCK THE DOCUMENT
Dim objDoc As New PCDClient.PCDDocObject
objDoc.SetDST(RDIMSAPI._sDST)
objDoc.SetObjectType("0_RDIMSPROF_SYS")
objDoc.SetProperty("%TARGET_LIBRARY", RDIMSAPI._Library)
objDoc.SetProperty("%OBJECT_IDENTIFIER", DocNumber)
objDoc.SetProperty("%VERSION_ID", VersionID)
objDoc.SetProperty("%STATUS", "%UNLOCK")
objDoc.Update()
objDoc.Fetch()
objDoc = Nothing
If Doc.objDoc.ErrNumber <> 0 Then
Throw New Exception(Doc.objDoc.ErrNumber & " - " & Doc.objDoc.ErrDescription)
End If
'RELEASE ALL OBJECTS AND RETURN DOCUMENT NUMBER
objPutDoc = Nothing
Catch ex As Exception
'IF EXCEPTION, LOG ERROR AND DISPLAY MESSAGE
Throw New Exception("(" & Me.GetType().FullName & "." & New StackTrace(0).GetFrame(0).GetMethod.Name & ") " & ex.Message)
Exit Sub
End Try
End Sub
I don't know if you're still trying. But here's my C# code for this. It's part of a larger module, so it won't work immediately. The profile parameter would be for example "DEF_PROF".
This also uses the PCDClientLib. My understanding is that these are serverside libraries, wich you should use only on the server. And that you should use the lib you've already used for clientside code.
// All variable prepended with an underscore are class fields etc...
// DMImportException is a custom exception, nothing special really
/// <summary>
/// Import a file into the library previously logged in to.
/// </summary>
/// <param name="profile">The name of the used profile.</param>
/// <param name="profileNameValues">A dictionary of strings containing the profile values wich should be saved for the document.</param>
/// <param name="FileName">The path and filename of the file to import.</param>
public virtual void ImportFile(string profile, Dictionary<string, string> profileNameValues, string FileName)
{
if (!_isLoggedIn)
{
throw new DMImportException("Trying to import a file while not logged in into DM.");
}
int totalbyteswritten;
byte[] bdata;
bdata = file.readallbytes(filename);
pcddocobject objdoc = new pcddocobject();
objdoc.setproperty("%target_library", _library);
objdoc.setdst(_dst);
objdoc.setobjecttype(profile);
foreach(var profilenamevaluepair in profilenamevalues)
{
objdoc.setproperty(profilenamevaluepair.key, profilenamevaluepair.value);
}
objdoc.create();
if (objdoc.errnumber != 0)
{
throw new dmimportexception("error while creating a new objdoc. check the inner error.", objdoc.errnumber, objdoc.errdescription);
}
_docnumber = objDoc.GetReturnProperty("%OBJECT_IDENTIFIER").ToString();
_versionID = objDoc.GetReturnProperty("%VERSION_ID").ToString();
PCDPutDoc objPutDoc = new PCDPutDoc();
objPutDoc.SetDST(_dst);
objPutDoc.AddSearchCriteria("%TARGET_LIBRARY", _library);
objPutDoc.AddSearchCriteria("%DOCUMENT_NUMBER", _docNumber);
objPutDoc.AddSearchCriteria("%VERSION_ID", _versionID);
objPutDoc.Execute();
if (objPutDoc.ErrNumber != 0)
{
throw new DMImportException("RecentEdit Failure on Execute: Error while trying to get a handle to the newly created doc. Check the inner error.", objPutDoc.ErrNumber, objPutDoc.ErrDescription);
}
objPutDoc.NextRow();
PCDPutStream objPutStream = (PCDPutStream)objPutDoc.GetPropertyValue("%CONTENT");
objPutStream.Write((object)bdata, (int)bdata.Length, out TotalBytesWritten);
objPutStream.SetComplete();
objPutStream = null;
objDoc = null;
objDoc = new PCDDocObject();
objDoc.SetDST(_dst);
objDoc.SetObjectType(profile);
objDoc.SetProperty("%TARGET_LIBRARY", _library);
objDoc.SetProperty("%OBJECT_IDENTIFIER", _docNumber);
objDoc.SetProperty("%VERSION_ID", _versionID);
objDoc.SetProperty("%STATUS", "%UNLOCK");
objDoc.Update();
if (objDoc.ErrNumber != 0)
{
throw new DMImportException("Error while trying to unlock the just imported file. Check the inner error.", objDoc.ErrNumber, objDoc.ErrDescription);
}
objPutDoc = null;
objDoc = null;
return;
}
P.S. I'd recommend you update to a later version of eDocs (we're upgrading from 5.1.0.5 to 5.2.1 end of this week ;-D)
--- EDIT ---
I think you need
Application.CurrentLibrary.CreateProfile("PROF_DEF").CreateVersionFromFile( /* filePath is one of the params */);
if you really need to do this with the DM Ext. API instead of the DM API

Resources