I am new to open xml sdk and i haven't much idea on how relationship work for wordprocessing document. I want to remove webtask-pane from my existing document which contains webtask-pane and its added through programmatically.
After deleting WebExtensionPart from WordprocessingDocument using open office xml.
Result : document get corrupted.
Reason : Relationship part is exists after deleting WebExtensionPart.
Code :
public static void RemoveTaskPaneExt(WordprocessingDocument package)
{
WebExTaskpanesPart webExTaskpanesPart1 = package.GetPartsOfType<WebExTaskpanesPart>().FirstOrDefault();
if (webExTaskpanesPart1 != null)
{
WebExtensionPart aWebExtension =
webExTaskpanesPart1.GetPartsOfType<WebExtensionPart>()
.Where(
x =>
x.WebExtension.WebExtensionStoreReference.Id ==
System.Configuration.ConfigurationManager.AppSettings["PaneID"])
.FirstOrDefault();
if (aWebExtension != null)
{
bool result = package.WebExTaskpanesPart.DeletePart(aWebExtension);
}
}
}
Please help.
Thanks in advance.
I got the answer using removing all children of task pane.
public static void RemoveTaskPaneExt(WordprocessingDocument package)
{
WebExTaskpanesPart webExTaskpanesPart1 = package.GetPartsOfType<WebExTaskpanesPart>().FirstOrDefault();
if (webExTaskpanesPart1 != null)
{
WebExtensionPart aWebExtension =
webExTaskpanesPart1.GetPartsOfType<WebExtensionPart>()
.Where(
x =>
x.WebExtension.WebExtensionStoreReference.Id ==
System.Configuration.ConfigurationManager.AppSettings["PaneID"])
.FirstOrDefault();
if (aWebExtension != null)
{
webExTaskpanesPart1.Taskpanes.RemoveAllChildren();
bool result = package.WebExTaskpanesPart.DeletePart(aWebExtension);
}
}
}
Happy coding!
The following will remove all WebExtensionTaskpanes and your Word file will be valid. Call this instead of your method above.
private static void RemoveWebExtensionPart(WordprocessingDocument package)
{
WebExTaskpanesPart webExTaskpanesPart1 = package.GetPartsOfType<WebExTaskpanesPart>().FirstOrDefault();
if (webExTaskpanesPart1 != null)
{
bool result2 = package.DeletePart(webExTaskpanesPart1);
}
}
Related
I am new to VSTO word Addin,the end goal is to check if the custom document property exists.Read all the available articles online with no breakthrough.
Started of with this code
public void chk()
{
if (this.Application.ActiveDocument.CustomDocumentProperties["ObjectType"].Value = 0)
{
MessageBox.Show("Please select an object");
}
}
This throws the error
Value does not fall within bounds error
Modified the code to create a custom document property object as below and it gives me the same error on
if(this.Application.ActiveDocument.CustomDocumentProperties["ObjectType"].Value
= 0)
public void chk()
{
dynamic properties = null;
properties = this.Application.ActiveDocument.CustomDocumentProperties;
properties.Add("Name",false,Office.MsoDocProperties.msoPropertyTypeString, "ObjectType");
properties.Add("LinkToContent",false, Office.MsoDocProperties.msoPropertyTypeBoolean,false);
properties.Add("Type",false,Office.MsoDocProperties.msoPropertyTypeNumber, 0);
if(this.Application.ActiveDocument.CustomDocumentProperties["ObjectType"].Value = 0)
{
MessageBox.Show("Please select an object");
}
}
Requesting you to suggest the steps to fix the issue. Please let me know if more information is required.
You can iterate over all properties and check their names, compare two approaches:
void TestProperties()
{
Microsoft.Office.Core.DocumentProperties properties;
properties = (Office.DocumentProperties)this.CustomDocumentProperties;
if (ReadDocumentProperty("Project Name") != null)
{
properties["Project Name"].Delete();
}
properties.Add("Project Name", false,
Microsoft.Office.Core.MsoDocProperties.msoPropertyTypeString,
"White Papers");
}
private string ReadDocumentProperty(string propertyName)
{
Office.DocumentProperties properties;
properties = (Office.DocumentProperties)this.CustomDocumentProperties;
foreach (Office.DocumentProperty prop in properties)
{
if (prop.Name == propertyName)
{
return prop.Value.ToString();
}
}
return null;
}
I've done a fair bit of research, but I can't find anyone who has the same problem as me (sadly). I am using LiteDB to create a NoSQL database.
When the program first runs and the database is created, the query in the example below works just fine. When I restart the program, it fails saying that it is null. The weird thing is, if I do a count it returns 8 records. So something exists - why can't I pull it out?
Here is my code:
public class ExternalTools
{
public int Id { get; set; }
public string Name { get; set; }
public string[] Types { get; set; }
}
public void GetAll()
{
var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
var folderPath = localFolder.Path;
var filePath = Path.Combine(folderPath, #"MyData4.db");
using (var db = new LiteDatabase(filePath))
{
Tools = db.GetCollection<ExternalTools>("externalTools");
if (Tools.Count() == 0)
{
CreateToolList();
// Index document using document Name property
Tools.EnsureIndex(x => x.Name);
}
}
Debug.WriteLine(Tools.Count());
var temp = Tools.FindAll(); // null error
var test = Tools.FindById(1); // another null error
Debug.WriteLine(test.Name); //
}
Thanks!
Well, I figured it out (so many hours of debugging wasted!) My code is in the wrong spot, if I move it into the using statement it works just fine. I suspect this has to do with the fact that on the first run it's adding stuff into the colection so it has the proper reference. Regardless, this code works:
using (var db = new LiteDatabase(filePath))
{
Tools = db.GetCollection<ExternalTools>("externalTools");
if (Tools.Count() == 0)
{
CreateToolList();
// Index document using document Name property
Tools.EnsureIndex(x => x.Name);
}
Debug.WriteLine(Tools.Count());
var temp = Tools.FindAll(); // null error
var test = Tools.FindById(1); // another null error
Debug.WriteLine(test.Name); //
}
I'm developing a code gen (VSIX) for my team and I'm intendedly using Roslyn as a fundamental engine after I have struggling with VSIX extensibility framework.
My code gen is currently able generate a new csproj for the solution and able to churn out boilerplate code base based on Templating project from VSIX extensibility. As ambitious I am, I'm trying not to rely on static templating project and use Roslyn to churn out the code instead.
My solution has a list of folders and each folder has a list of csproj.
My Question 1 is I'm trying to use Roslyn Workspace API to detect the current document (.cs) that has been open in code editor or am trying to get the current doc id of the selected cs file I right click from the solution explorer.
I have tried to use AdhocWorkspace which so far have failed as I'm not able to get any.
Question 2: If I were to use AdhocWorkspace, am I able to change the default namespace in the csproj properties? Or was it not part of the functionalities in Roslyn Workspace API at the moment?
Thanks.
For #1 some code I have to do the same thing. I am doing stuff with the cursor so I'm going through caretPosition (cursor). There are other ways but the gist is the same, get the current textview the go from that to Roslyn.
You will need to install Microsoft.CodeAnalysis.EditorFeatures.Text which brings in allot of code analysis packages but allows you to use he GetOpenDocumentInCurrentContextWithChanges extension applied on ITextSnapshot
private IVsEditorAdaptersFactoryService GetEditorAdaptersFactoryService()
{
IComponentModel componentModel =(IComponentModel)GetService(typeof(SComponentModel));
return componentModel.GetService<IVsEditorAdaptersFactoryService>();
}
private Microsoft.VisualStudio.Text.Editor.IWpfTextView GetTextView()
{
IVsTextManager textManager = (IVsTextManager)GetService(typeof(SVsTextManager));
if (textManager == null)
return null;
IVsTextView textView = null;
textManager.GetActiveView(1, null, out textView);
if (textView == null)
return null;
return GetEditorAdaptersFactoryService().GetWpfTextView(textView);
}
//code to get the doc
Microsoft.VisualStudio.Text.Editor.IWpfTextView textView = GetTextView();
if (textView != null)
{
SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition;
Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
//do stuff with Roslyn Document
}
"or am trying to get the current doc id of the selected cs file I right click from the solution explorer."
This is really ugly but what I used from a different SO post (don't remember the author) that does work well.
private static bool IsSingleProjectItemSelection(out IVsHierarchy hierarchy, out uint itemid)
{
hierarchy = null;
itemid = VSConstants.VSITEMID_NIL;
int hr = VSConstants.S_OK;
var monitorSelection = Package.GetGlobalService( typeof( SVsShellMonitorSelection ) ) as IVsMonitorSelection;
var solution = Package.GetGlobalService( typeof( SVsSolution ) ) as IVsSolution;
if (monitorSelection == null || solution == null)
return false;
IVsMultiItemSelect multiItemSelect = null;
IntPtr hierarchyPtr = IntPtr.Zero;
IntPtr selectionContainerPtr = IntPtr.Zero;
try
{
hr = monitorSelection.GetCurrentSelection( out hierarchyPtr, out itemid, out multiItemSelect, out selectionContainerPtr );
if (ErrorHandler.Failed( hr ) || hierarchyPtr == IntPtr.Zero || itemid == VSConstants.VSITEMID_NIL)
return false;
// multiple items are selected
if (multiItemSelect != null)
return false;
// there is a hierarchy root node selected, thus it is not a single item inside a project
if (itemid == VSConstants.VSITEMID_ROOT)
return false;
hierarchy = Marshal.GetObjectForIUnknown( hierarchyPtr ) as IVsHierarchy;
if (hierarchy == null)
return false;
Guid guidProjectID = Guid.Empty;
if (ErrorHandler.Failed( solution.GetGuidOfProject( hierarchy, out guidProjectID ) ))
return false;
// if we got this far then there is a single project item selected
return true;
}
finally
{
if (selectionContainerPtr != IntPtr.Zero)
Marshal.Release( selectionContainerPtr );
if (hierarchyPtr != IntPtr.Zero)
Marshal.Release( hierarchyPtr );
}
}
IVsHierarchy hierarchy = null;
uint itemid = VSConstants.VSITEMID_NIL;
if (!IsSingleProjectItemSelection(out hierarchy, out itemid))
return;
string itemFullPath = null;
((IVsProject)hierarchy).GetMkDocument(itemid, out itemFullPath);
if (itemFullPath.EndsWith(".cs"))
Here What I am trying to do, my employer want to be able to be able do 301 redirect with regex expression with the alias in Sitecore so the way I am trying to implement this is like this!
a singleline text field
with a checkbox to tell sitecore it will be a regex expression I am a noob in .NET and Sitecore how can I implement this ? here a exemple http://postimg.org/image/lwr524hkn/
I need help the exemple of redirect I want handle is like this, this is a exemple of the redirect I want to do it could be product at the place of solution.
exemple.com/en/solution/platform-features to
exemple.com/en/platform-features
I base the code from http://www.cmssource.co.uk/blog/2011/December/modifying-sitecore-alias-to-append-custom-query-strings-via-301-redirect this is for query string I want to use regex expression.
namespace helloworld.Website.SC.Common
{
public class AliasResolver : Sitecore.Pipelines.HttpRequest.AliasResolver
{
// Beginning of the Methods
public new void Process(HttpRequestArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (!Settings.AliasesActive)
{
Tracer.Warning("Aliases in AliasResolver are not active.");
}
else
{
Sitecore.Data.Database database = Context.Database;
if (database == null)
{
Tracer.Warning("There is no context in the AliasResolver.");
}
else
{
{
Profiler.StartOperation("Resolve virgin alias pipeline.");
Item item = ItemManager.GetItem(FileUtil.MakePath("/sitecore/system/aliases", args.LocalPath, '/'), Language.Current, Sitecore.Data.Version.First, database, SecurityCheck.Disable);
if (item != null)
{
//Alias existis (now we have the alias item)
if (item.Fields["Regular Expressions"] != null)
{
if (!String.IsNullOrEmpty(item.Fields["Regular Expressions"].Value) && !args.Url.QueryString.Contains("aproc"))
{
var reg = new Regex(#"(?<Begin>([^/]*/){2})[^/]*/(?<End>.*)");
var match = reg.Match(#"exemple.com/en/solution/platform-features");
var result = match.Groups["Begin"].Value + match.Groups["End"].Value;
}
}
}
Profiler.EndOperation();
}
catch (Exception ex)
{
Log.Error("Had a problem in the VirginAliasResolver. Error: " + ex.Message, this);
}
}
}
}
///<summary>
/// Once a match is found and we have a Sitecore Item, we can send the 301 response.
///</summary>
private static void SendResponse(string redirectToUrl, HttpRequestArgs args)
{
args.Context.Response.Status = "301 Moved Permanently";
args.Context.Response.StatusCode = 301;
args.Context.Response.AddHeader("Location", redirectToUrl);
args.Context.Response.End();
}
}
}
PS: I know they have module for this but my employer want it done that way and I am reaching for help since it's been a week I'm trying to add this feature
So if I understand correctly, you do not want to select an Alias by path:
Item item = ItemManager.GetItem(FileUtil.MakePath("/sitecore/system/aliases", args.LocalPath, '/'), Language.Current, Sitecore.Data.Version.First, database, SecurityCheck.Disable);
But rather find an Alias comparing a Regex field to the Url. I have not tested this, but it could be someting like:
var originalUrl = HttpContext.Current.Request.Url;
var allAliases = Sitecore.Context.Database.SelectItems("/sitecore/system/aliases//*");
var foundAlias = allAliases.FirstOrDefault( alias =>
!string.IsNullOrEmpty(alias["Regular Expressions"]) &&
Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), alias["Regular Expressions"]));
Then, if foundAlias != null, you can retrieve the url and redirect like you do in your private SendResponse function.
var linkField = (LinkField)foundAlias.Fields["linked item"];
var targetUrl = linkField.Url;
using (new SecurityDisabler())
{
if (string.IsNullOrEmpty(targetUrl) && linkField.TargetItem != null)
targetUrl = LinkManager.GetItemUrl(linkField.TargetItem);
}
SendResponse(targetUrl, args);
Again, I have not tested this so don't shoot me if it needs some corrections, but this should help you get on your way.
This is what my team and I chose to do for our school project. Well, actually we haven't decided on how to parse the C# source files yet.
What we are aiming to achieve is, perform a full analysis on a C# source file, and produce up a report.
In which the report is going to contain stuff that happening in the codes.
The report only has to contain:
string literals
method names
variable names
field names
etc
I'm in charge of looking into this Irony library. To be honest, I don't know the best way to sort the data out into a clean readable report. I am using the C# grammar class packed with the zip.
Is there any step where I can properly identify each node children? (eg: using directives, namespace declaration, class declaration etc, method body)
Any help or advice would be very much appreciated. Thanks.
EDIT: Sorry I forgot to say we need to analysis the method calls too.
Your main goal is to master the basics of formal languages. A good start-up might be found here. This article describes the way to use Irony on the sample of a grammar of a simple numeric calculator.
Suppose you want to parse a certain file containing C# code the path to which you know:
private void ParseForLongMethods(string path)
{
_parser = new Parser(new CSharpGrammar());
if (_parser == null || !_parser.Language.CanParse()) return;
_parseTree = null;
GC.Collect(); //to avoid disruption of perf times with occasional collections
_parser.Context.SetOption(ParseOptions.TraceParser, true);
try
{
string contents = File.ReadAllText(path);
_parser.Parse(contents);//, "<source>");
}
catch (Exception ex)
{
}
finally
{
_parseTree = _parser.Context.CurrentParseTree;
TraverseParseTree();
}
}
And here is the traversal method itself with counting some info in the nodes. Actually this code counts the number of statements in every method of the class. If you have any question you are always welcome to ask me
private void TraverseParseTree()
{
if (_parseTree == null) return;
ParseNodeRec(_parseTree.Root);
}
private void ParseNodeRec(ParseTreeNode node)
{
if (node == null) return;
string functionName = "";
if (node.ToString().CompareTo("class_declaration") == 0)
{
ParseTreeNode tmpNode = node.ChildNodes[2];
currentClass = tmpNode.AstNode.ToString();
}
if (node.ToString().CompareTo("method_declaration") == 0)
{
foreach (var child in node.ChildNodes)
{
if (child.ToString().CompareTo("qual_name_with_targs") == 0)
{
ParseTreeNode tmpNode = child.ChildNodes[0];
while (tmpNode.ChildNodes.Count != 0)
{ tmpNode = tmpNode.ChildNodes[0]; }
functionName = tmpNode.AstNode.ToString();
}
if (child.ToString().CompareTo("method_body") == 0) //method_declaration
{
int statementsCount = FindStatements(child);
//Register bad smell
if (statementsCount>(((LongMethodsOptions)this.Options).MaxMethodLength))
{
//function.StartPoint.Line
int functionLine = GetLine(functionName);
foundSmells.Add(new BadSmellRegistry(name, functionLine,currentFile,currentProject,currentSolution,false));
}
}
}
}
foreach (var child in node.ChildNodes)
{ ParseNodeRec(child); }
}
I'm not sure this is what you need but you could use the CodeDom and CodeDom.Compiler namespaces to compile the C# code, and than analyze the results using Reflection, something like:
// Create assamblly in Memory
CodeSnippetCompileUnit code = new CodeSnippetCompileUnit(classCode);
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerResults results = provider.CompileAssemblyFromDom(compileParams, code);
foreach(var type in results.CompiledAssembly)
{
// Your analysis go here
}
Update: In VS2015 you could use the new C# compiler (AKA Roslyn) to do the same, for example:
var root = (CompilationUnitSyntax)tree.GetRoot();
var compilation = CSharpCompilation.Create("HelloTDN")
.AddReferences(references: new[] { MetadataReference.CreateFromAssembly(typeof(object).Assembly) })
.AddSyntaxTrees(tree);
var model = compilation.GetSemanticModel(tree);
var nameInfo = model.GetSymbolInfo(root.Usings[0].Name);
var systemSymbol = (INamespaceSymbol)nameInfo.Symbol;
foreach (var ns in systemSymbol.GetNamespaceMembers())
{
Console.WriteLine(ns.Name);
}