C# - AddStore not working properly in Outlook - c#

I have been attempting this all morning (VS2K10, OL2K7, .NET 3.5) and my PSTs never attach. I've modified the path to include escaped slashes, no dice. I occasionally see the PST get added then disappear when I hit the command bar button for which I am trying to program.
Here is a snip of my code:
void b_removedPSTs_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault)
{
string PSTToAdd = dd_removed_PSTs.Text;
foreach (PSTWithPath p in removedPSTs)
{
if (PSTToAdd == p.name)
{
olApp.Session.AddStore(#p.path);
}
}
UpdateRemovedList();
}
PSTWithPath is a custom class I've created as follows:
public class PSTWithPath
{
public string name;
public string path;
public Outlook.MAPIFolder mapifolder;
public PSTWithPath(string PSTName, string PSTPath, Outlook.MAPIFolder PSTMAPIFolder)
{
name = PSTName;
path = PSTPath;
mapifolder = PSTMAPIFolder;
}
Advice would be greatly appreciated.
Thanks,
Larry

I solved the issue. It seems that the function was being case sensitive. Not sure if this was a MS or Novell thing, but it's working now.

Related

Question about file reading and comparing

First Off I have a File That Looks Like This:
//Manager Ids
ManagerName: FirstName_LastName
ManagerLoginId: 12345
And a Text Box That has a five digit code(ex. 12345) That gets entered. When the Enter Key Is pressed it is assigned to a String called: "EnteredEmployeeId", Then What I need is to search the Entire file above for "EnteredEmployeeId" and if it matches then it will open another page, if it doesn't find that number then display a message(That tells you no employee Id found).
So essentially Im trying to open a file search the entire document for the Id then return true or false to allow it too either display an error or open a new page, and reset the EnteredEmployeeId to nothing.
My Code So Far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Rent_a_Car
{
public partial class Employee_Login_Page : Form
{
public Employee_Login_Page()
{
InitializeComponent();
}
string ManagersPath = #"C:\Users\Name\Visual Studios Project Custom Files\Rent A Car Employee Id's\Managers\Manager_Ids.txt"; //Path To Manager Logins
string EnteredEmployeeId;
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void Employee_Id_TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && //Checks Characters entered are Numbers Only and allows them
(e.KeyChar != '0'))
{
e.Handled = true;
}
else if (e.KeyChar == (char)13) //Checks if The "Enter" Key is pressed
{
EnteredEmployeeId = Employee_Id_TextBox.Text; //Assigns EnteredEmployeeId To the Entered Numbes In Text Box
bool result = ***IsNumberInFile***(EnteredEmployeeId, "ManagerLoginId:", ManagersPath);
if (result)
{
//open new window
}
else
{
MessageBox.Show("User Not Found");
}
}
}
}
}
This function will read through whole file and find if there is inserted code. It will work with strings (as it is output of your text box) and will return only true or false (employee is or is not in file) not his name, surname etc.
static bool IsNumberInFile(string numberAsString, string LineName, string FileName)
{
var lines = File.ReadAllLines(FileName);
foreach(var line in lines)
{
var trimmedLine = line.Replace(" ", ""); //To remove all spaces in file. Not expecting any spaces in the middle of number
if (!string.IsNullOrEmpty(trimmedLine) && trimmedLine.Split(':')[0].Equals(LineName) && trimmedLine.Split(':')[1].Equals(numberAsString))
return true;
}
return false;
}
//Example of use
String ManagersPath = #"C:\Users\Name\Visual Studios Project Custom Files\Employee Id's\Managers\Manager_Ids.txt"; //Path To Manager Logins
String EnteredEmployeeId;
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void Employee_Id_TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && //Checks Characters entered are Numbers Only and allows them
(e.KeyChar != '0'))
{
e.Handled = true;
}
else if (e.KeyChar == (char)13) //Checks if The "Enter" Key is pressed
{
EnteredEmployeeId = Employee_Id_TextBox.Text; //Assigns EnteredEmployeeId To the Entered Numbes In Text Box
bool result = IsNumberInFile(EnteredEmployeeId, "ManagerLoginId" , ManagersPath)
if(result)
//User is in file
else
//User is not in file
}
}
}
Short answer
Is your question about how to read your file?
private bool ManagerExists(int managerId)
{
return this.ReadManagers().Where(manager => manager.Id == managerId).Any();
}
private IEnumerable<Manager> ReadManagers()
{
using (var reader = System.IO.File.OpenText(managersFileName))
{
while (!reader.EndOfStream)
{
string lineManagerName = reader.ReadLine();
string lineMangerId = reader.ReadLine();
string managerName = ExtractValue(lineManagerName);
int managerId = Int32.Parse(ExtractValue(lineManagerId));
yield return new Manager
{
Id = managerId,
Name = managerName,
}
}
}
private string ExtractValue(string text)
{
// the value of the read text starts after the space:
const char separator = ' ';
int indexSeparator = text.IndexOf(separator);
return text.SubString(indexSeparator + 1);
}
Long Answer
I see several problems in your design.
The most important thing is that you intertwine your manager handling with your form.
You should separate your concerns.
Apparently you have the notion of a sequence of Managers, each Manager has a Name (first name, last name) and a ManagerId, and in future maybe other properties.
This sequence is persistable: it is saved somewhere, and if you load it again, you have the same sequence of Managers.
In this version you want to be able to see if a Manager with a given ManagerId exists. Maybe in future you might want more functionality, like fetching information of a Manager with a certain Id, or Fetch All managers, or let's go crazy: Add / Remove / Change managers!
You see in this description I didn't mention your Forms at all. Because I separated it from your Forms, you can use it in other forms, or even in a class that has nothing to do with a Form, for instance you can use it in a unit test.
I described what I needed in such a general from, that in future I might even change it. Users of my persistable manager collection wouldn't even notice it: I can put it in a JSON file, or XML; I can save the data in a Dictionary, a database, or maybe even fetch it from the internet.
All that users need to know, is that they have to create an instance of the class, using some parameters, and bingo, you can fetch Managers.
You also give users the freedom to decide how the data is to be saved: if they want to save it in a JSON file, changes in your form class will be minimal.
An object that stores sequences of objects is quite often called a Repository.
Let's create some classes:
interface IManager
{
public int Id {get;}
public string Name {get; set;}
}
interface IManagerRepository
{
bool ManagerExists(int managerId);
// possible future extensions: Add / Retrieve / Update / Delete (CRUD)
IManager Add(IManager manager);
IManager Find(int managerId);
void Update(IManager manager);
void Delete(int ManagerId);
}
class Manager : IManager
{
public Id {get; set;}
public string Name {get; set;}
}
class ManagerFileRepository : IManagerRepository,
{
public ManagerFileRepository(string fileName)
{
// TODO implement
}
// TODO: implement.
}
The ManagerFileRepository saves the managers in a file. It hides for the outside world how the file is internally structured. It could be your file format, it could be a CSV-file, or JSON / XML.
I also separated an interface, so if you later decide to save the data somewhere else, for instance in a Dictionary (for unit tests), or in a database, users of your Repository class won't see the difference.
Let's first see if you can use this class.
class MyForm : Form
{
const string managerFileName = ...
private IManagerRepository ManagerRepository {get;}
public MyForm()
{
InitializeComponent();
this.ManagerRepository = new ManagerFileRepository(managerFileName);
}
public bool ManagerExists(int managerId)
{
return this.ManagerRepository.ManagerExists(managerId);
}
Now let's handle your keyPress:
private void Employee_Id_TextBox_KeyPress(object sender, KeyPressEventArgs e)
{
TextBox textBox = (TextBox)sender;
... // code about numbers and enter key
int enteredManagerId = Int32.Parse(textBox.Text);
bool managerExists = this.ManagerExists(enteredManagerId);
if (managerExists) { ... }
}
This code seems to do what you want in an easy way. It looks transparent. The managerRepository is testable, reusable, simple to extend or change, because users won't notice this. So the class looks good. Let's implement
Implement ManagerFileRepository
There are several ways to implement reading the file:
(1) Read everything at construction time
and keep the read data in memory. If you add Managers they are not saved until you say so. Advantages: after initial startup it is fast. You can make changes and later decide not to save them anyway, so it is just like editing any other file. Disadvantage: if your program crashes, you have lost your changes.
(2) Read the file every time you need information
Advantage: data is always up-to-date, even if others edited the file while your program runs. If you change the manager collection it is immediately saved, so other can use it.
Which solution you choose depends on the size of the file and the importance of never losing data. If you file contains millions of records, then maybe it wasn't very wise to save the data in a file. Consider SQLite to save it in a small fairly fast database.
class ManagerFileRepository : IManagerRepository, IEnumerable<IManager>
{
private readonly IDictionary<int, IManager> managers;
public ManagerFileRepository(string FileName)
{
this.managers = ReadManagers(fileName);
}
public bool ManagerExists(int managerId)
{
return this.Managers.HasKey(managerId);
}
private static IEnumerable<IManager> ReadManagers(string fileName)
{
// See the short answer above
}
}
Room for improvement
If you will be using your manager repository for more things, consider to let the repository implement ICollection<IManager> and IReadOnlyCollection<IManager>. This is quite simple:
public IEnumerable<IManager> GetEnumerator()
{
return this.managers.Values.GetEnumerator();
}
public void Add(IManager manager)
{
this.managers.Add(manager.Id, manager);
}
// etc.
If you add functions to change the manager collection you'll also need a Save method:
public void Save()
{
using (var writer = File.CreateText(FullFileName))
{
const string namePrefix = "ManagerName: ";
const string idPrefix = "ManagerLoginId: ";
foreach (var manager in managers.Values)
{
string managerLine = namePrefix + manager.Name;
writer.WriteLine(managerLine);
string idLine = idPrefix + manager.Id.ToString();
writer.WriteLine(idLine);
}
}
}
Another method of improvement: your file structure. Consider using a more standard file structure: CSV, JSON, XML. There are numerous NUGET packages (CSVHelper, NewtonSoft.Json) that makes reading and writing Managers much more robust.
Summary
Because you separated the concerns of persisting your managers from your form, you can reuse the manager repository, especially if you need functionality to Add / Retrieve / Update / Delete managers.
Because of the separation it is much easier to unit test your functions. And future changes won't hinder users of the repository, because they won't notice that the data has changed.
If your Manager_Ids.txt is in the following format, you can use File.ReadLine() method to traverse the text and query it.
ManagerName: FirstName_LastName1
ManagerLoginId: 12345
ManagerName: FirstName_LastName2
ManagerLoginId: 23456
...
Here is the demo that traverse the .txt.
string ManagersPath = #"D:\Manager_Ids.txt";
string EnteredEmployeeId;
private void textBox_id_KeyDown(object sender, KeyEventArgs e)
{
int counter = 0;
bool exist = false;
string line;
string str = "";
if (e.KeyCode == Keys.Enter)
{
EnteredEmployeeId = textBox_id.Text;
System.IO.StreamReader file =
new System.IO.StreamReader(ManagersPath);
while ((line = file.ReadLine()) != null)
{
str += line + "|";
if (counter % 2 != 0)
{
if (str.Split('|')[1].Split(':')[1].Trim() == EnteredEmployeeId)
{
str = str.Replace("|", "\n");
MessageBox.Show(str);
exist = true;
break;
}
str = "";
}
counter++;
}
if (!exist)
{
MessageBox.Show("No such id");
}
file.Close();
}
}
Besides, I recommend to use "xml", "json" or other formats to serialize the data. About storing the data in "xml", you can refer to the following simple demo.
<?xml version="1.0"?>
<Managers>
<Manager>
<ManagerName>FirstName_LastName1</ManagerName>
<ManagerLoginId>12345</ManagerLoginId>
</Manager>
<Manager>
<ManagerName>FirstName_LastName2</ManagerName>
<ManagerLoginId>23456</ManagerLoginId>
</Manager>
</Managers>
And then use LINQ to XML to query the id.
string ManagersPath = #"D:\Manager_Ids.xml";
string EnteredEmployeeId;
private void textBox_id_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
EnteredEmployeeId = textBox_id.Text;
XElement root = XElement.Load(ManagersPath);
IEnumerable<XElement> manager =
from el in root.Elements("Manager")
where (string)el.Element("ManagerLoginId") == EnteredEmployeeId
select el;
if(manager.Count() == 0)
{
MessageBox.Show("No such id");
}
foreach (XElement el in manager)
MessageBox.Show("ManagerName: " + (string)el.Element("ManagerName") + "\n"
+ "ManagerLoginId: " + (string)el.Element("ManagerLoginId"));
}
}

Xcode Cocoa - Drag Drop from NSTableView to Finder

I want my MacOS App to be able to Drag a item from NSTableView to an other Application like Logic Pro X, Finder, etc.
The items in this TableViews are classes I created which are representing Files on my HD.
public class AudioFile
{
#region Computed Propoperties
public string Filename { get; set; } = "";
public string Filepath { get; set; } = "";
#endregion
public AudioFile()
{
}
public AudioFile(string filename, string filepath)
{
this.Filename = filename;
this.Filepath = filepath;
}
}
Unfortunately I can't find a solution for Swift or Objective-C which I could translate to C# (Xamarin). Does anyone know one or has some code that could help here?
Thanks for your help!
I know nothing about C#, but you asked for a solution in Swift or Objective-C. That I can help with! The below is Swift 4.
First of all, make sure your ViewController is the table view's data source:
class ViewController: NSViewController, NSTableViewDataSource
You will also need to make that connection either in code or in IB.
You then need to set your table view as a dragging source. Choose the operation you want, usually either .move or .copy:
tableView.setDraggingSourceOperationMask(.move, forLocal: false)
This example assumes that you're using an ArrayController to manage the content of the tableView. You really should be, it makes a host of things easier. Also, this example is for dragging multiple files. (It will work for a single file, but there are other approaches if you only ever want to drag one.)
In your ViewController class, implement this method:
func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
var filePaths = [String]()
// Swift 4 hack--the FilenamesPboardType is missing
let NSFilenamesPboardTypeTemp = NSPasteboard.PasteboardType("NSFilenamesPboardType")
pboard.addTypes([NSFilenamesPboardTypeTemp], owner: nil)
if let audioFiles = audioFilesArrayController.arrangedObjects as? [AudioFile] {
for i in rowIndexes {
filePaths.append(audioFiles[i].Filepath)
}
}
pboard.setPropertyList(filePaths, forType: NSFilenamesPboardTypeTemp)
return true
}
You can learn more about the NSFilenamesPboardTypeTemp hack here.
And that's it! Recompile and you should be able to move one or more of your files by dragging them to a Finder window. Simple. :-)

Using RichEditDocumentServer to change from rtf to text

I am trying to convert RTF to plain text in a c# program. I figured out how to do it but it isn't very clean. It uses RichTextBox which I'm not a huge fan of:
using (System.Windows.Forms.RichTextBox rtfBox = new System.Windows.Forms.RichTextBox())
{
rtfBox.Rtf = cTrans.NoteDescription;
tItem.ProcedureShortDescription = rtfBox.Text;
}
I was wondering if there is a better way to go about accomplishing this. Perhaps using RichEditDocumentServer? I could not find a ton of info on it though and was wondering if I could get some help on it. My thought was:
var documentServer = new RichEditDocumentServer();
documentServer.Document.RtfText = cTrans.NoteDescription;
tItem.ProcedureShortDescription = documentServer.Document.Text;
I did some more digging and this works. I figured I'd just post this as I couldn't see it answered anywhere on the site. I'm not sure if that is proper protocol.
I ended up putting it in a helper class so it can be called if needed again:
namespace ABELSoft.Dental.Interface.Helper
{
public class RtfToText
{
public static string convert(string rtfText)
{
string _text;
var documentServer = new RichEditDocumentServer();
documentServer.Document.RtfText = rtfText;
_text = documentServer.Document.Text;
return _text;
}
}
}
This is how I called it:
tItem.ProcedureShortDescription = RtfToText.convert(cTrans.NoteDescription);

Getting path to image

everybody!
I know, that probably the question was asked many times, but anyway..
The problem is:
I have a solution with 2 projects (C# Class Library and Web-project).
In class library project I've overriden a text box control, so it has built-in validations. On local server everything works nice, but when I upload published project, the problems begin.
Here's the code:
[Browsable(true)]
[Category("Appearance")]
[DefaultValue("~/images/alert.png")]
public string AlertImageUrl
{
get
{
string path = HttpContext.Current.Server.MapPath("~/images/alert.png");
return GetPropertyValue<string>("AlertImageUrl", path);
}
set
{
SetPropertyValue("AlertImageUrl", value);
}
}
protected override void Render(HtmlTextWriter writer)
{
this.Attributes["onfocus"] = "var objs = this.parentNode.childNodes; for (var i = 0; i < objs.length; i++) {if (objs[i].id == 'imgAlert') { objs[i].style.display = 'none'; } }";
writer.WriteFullBeginTag("span");
base.Render(writer);
if (!_validator.IsValid)
{
writer.WriteBeginTag("img");
writer.WriteAttribute("id", "imgAlert");
writer.WriteAttribute("runat", "server");
writer.WriteAttribute("style", "left: -20px; top: 3px;");
writer.WriteAttribute("src", AlertImageUrl);
writer.WriteEndTag("img");
}
writer.WriteEndTag("span");
}
Image is located in App_Themes/Theme_name/images/alert.png
How to get AlertImageUrl correctly? Strange, if I manually set it returns correct path, but WriteAttribute - no..
Any help is appreciated,
Regards, Maris
Use ResolveClientUrl method instead of the Server.MapPath

AutoCorrect Text C# Word

I'm trying to use word to automatically correct some text that is not in English the problem is that when i use the SpellCheck function the "Spell and Grammar" dialog box pop-up and waits for users input and i want the text to be corrected automatically. So my question is how do i solve this ?
using System.Collections.Generic;
using Microsoft.Office.Interop.Word;
using Word = Microsoft.Office.Interop.Word;
using TobyCL.ro.toby.StringOperations;
namespace namespace.ro.toby
{
class WordProofing:IProof
{
private readonly Word.Application _wordApp;
private readonly Word.Document _wordDoc;
private static object _oEndOfDoc = "\\endofdoc";
public WordProofing()
{
_wordApp = new Word.Application {Visible = false};
_wordDoc = _wordApp.Documents.Add();
}
public void Close()
{
object obj = Word.WdSaveOptions.wdDoNotSaveChanges;
_wordDoc.Close(ref obj);
_wordApp.Quit(ref obj);
}
#region Implementation of IProof
public string Proof(string proofText)
{
Range wRng = _wordDoc.Bookmarks.get_Item(ref _oEndOfDoc).Range;
wRng.Text = proofText;
_wordDoc.CheckSpelling(IgnoreUppercase: true,AlwaysSuggest:false);
string str = wRng.Text;
wRng.Text = "";
return str;
}
#endregion
}
}
I wrote this code a few days ago and it worked. The problem is that i uninstall proofing tools to run some tests and now i keep getting that dialog so i'm thinking that may i have to set some Word settings or i've changed something in my code without knowing. Any help would be greatly appreciated.
I am using Microsoft Office Word 2010
For whoever might be interested this is the way i managed to solve it, but it really takes a lot of time so any improvements or new ideas are welcomed.
using Microsoft.Office.Interop.Word;
class WordProofing
{
private Application _wordApp;
private readonly Document _wordDoc;
private static object _oEndOfDoc = "\\endofdoc";
public WordProofing()
{
_wordApp = new Application { Visible = false };
_wordDoc = _wordApp.Documents.Add();
}
public void Close()
{
_wordDoc.Close(WdSaveOptions.wdDoNotSaveChanges);
_wordApp.Quit();
}
public string Proof(string proofText)
{
Range wRng = _wordDoc.Bookmarks.get_Item(ref _oEndOfDoc).Range;
wRng.Text = proofText;
ProofreadingErrors spellingErros = wRng.SpellingErrors;
foreach (Range spellingError in spellingErros)
{
SpellingSuggestions spellingSuggestions =
_wordApp.GetSpellingSuggestions(spellingError.Text,IgnoreUppercase:true);
foreach (SpellingSuggestion spellingSuggestion in spellingSuggestions)
{
spellingError.Text = spellingSuggestion.Name;
break;
}
}
string str = wRng.Text;
wRng.Text = "";
return str;
}
}
Which MS Word version are you using?
By default the spell checker will show you the dialog box. To disable the dialog box there are two ways that I know.
1) Using Code, automatically choose the first option from Auto Correct.
It is something like this
AutoCorrect.Entries.Add Name:="AdSAD", Value:="Assad"
2) Or use the menu option. Please refer to this link.
Topic: Automatically correct spelling with words from the main dictionary
Link: http://office.microsoft.com/en-us/word-help/automatically-correct-spelling-with-words-from-the-main-dictionary-HA010174790.aspx
Do let me know if this is not what you want?

Categories