Skip to content

Commit 21dc5ad

Browse files
ThunderFrameretailcoder
authored andcommitted
Fixes GetDisplayName (#1646)
* Adds RTF and XML Spreadsheet data formats Still need to RTF-escape content values Temporary Fix in InspectionResultBase, for instances of unsaved filename boom. * XML Spreadsheet builds from XMLWriter instead of StringBuilder Adds ColumnInfos helper classes, for specifying and formatting column titles, not yet fully implemented. * Improves Clipboard export formatter Adds a DocumentName property to QualifiedModuleName, adds DocumentName to column output. * adds notes and placeholder for Outllook's Application.Run alternative not implemented - need to write to events in the ThisOutlookSession before this will work. * Adds columns to inspection results, and adds column titles changes to Column alignment, font weights, colspans * improvements to InspectionResults Clipboard Refines DocumentName of QualifiedModule * Adds DisplayName and Title for Projects and Components ProjectDisplayName eg. `Book1` ProjectTitle eg. `VBA Project (Book1) ComponentDisplayName eg. `Home` ComponentTitle eg. `shtHome (Home)` * corrects ComponentTitle behaviour still needs testing across multiple hosts. * removes temporary comments * adds DisplayName to extra QualifiedModuleName constructor was out of Sync with Next, so had to add these fields to the newly discovered ctor. * Adds Unit Test support for Visio, clipboard formats for Test Explorer Adds Start and End Times for Unit Test results (only viewable in Clipboard exports) Title and Headings aren't yet localized. No plain-text clipboard export format yet * Adjusts treeview border to correct jagged edge of Code Explorer window sought and received @Hosch250 approval * Adds Copy button to Code Explorer, allows copy of *all* User Declarations WIP... * Fixes GetDisplayName Adds extra method for projects that have documents without a document-component (eg. PowerPoint)
1 parent 5156050 commit 21dc5ad

File tree

6 files changed

+143
-19
lines changed

6 files changed

+143
-19
lines changed

RetailCoder.VBE/Navigation/CodeExplorer/CodeExplorerViewModel.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Collections.ObjectModel;
4+
using System.Globalization;
5+
using System.IO;
46
using System.Linq;
7+
using System.Windows;
58
using System.Windows.Input;
69
using Microsoft.Vbe.Interop;
10+
using Rubberduck.Common;
711
using Rubberduck.Navigation.Folders;
812
using Rubberduck.Parsing.Annotations;
913
using Rubberduck.Parsing.Symbols;
@@ -22,6 +26,7 @@ public sealed class CodeExplorerViewModel : ViewModelBase, IDisposable
2226
{
2327
private readonly FolderHelper _folderHelper;
2428
private readonly RubberduckParserState _state;
29+
private readonly IClipboardWriter _clipboard;
2530

2631
public CodeExplorerViewModel(FolderHelper folderHelper, RubberduckParserState state, List<ICommand> commands)
2732
{
@@ -30,6 +35,8 @@ public CodeExplorerViewModel(FolderHelper folderHelper, RubberduckParserState st
3035
_state.StateChanged += ParserState_StateChanged;
3136
_state.ModuleStateChanged += ParserState_ModuleStateChanged;
3237

38+
_clipboard = new ClipboardWriter();
39+
3340
_refreshCommand = commands.OfType<CodeExplorer_RefreshCommand>().FirstOrDefault();
3441
_refreshComponentCommand = commands.OfType<CodeExplorer_RefreshComponentCommand>().FirstOrDefault();
3542
_navigateCommand = commands.OfType<CodeExplorer_NavigateCommand>().FirstOrDefault();
@@ -59,6 +66,38 @@ public CodeExplorerViewModel(FolderHelper folderHelper, RubberduckParserState st
5966
_commitCommand = commands.OfType<CodeExplorer_CommitCommand>().FirstOrDefault();
6067
_undoCommand = commands.OfType<CodeExplorer_UndoCommand>().FirstOrDefault();
6168

69+
//_copyResultsCommand = commands.OfType<CodeExplorer_CopyResultsCommand>().FirstOrDefault();
70+
71+
_copyResultsCommand = new DelegateCommand(param =>
72+
{
73+
const string XML_SPREADSHEET_DATA_FORMAT = "XML Spreadsheet";
74+
75+
ColumnInfo[] ColumnInfos = { new ColumnInfo("Project"), new ColumnInfo("Folder"), new ColumnInfo("Component"), new ColumnInfo("Declaration Type"), new ColumnInfo("Scope"),
76+
new ColumnInfo("Name"), new ColumnInfo("Return Type") };
77+
78+
// this.ProjectName, this.CustomFolder, this.ComponentName, this.DeclarationType.ToString(), this.Scope
79+
var aDeclarations = _state.AllUserDeclarations.Select(declaration => declaration.ToArray()).ToArray();
80+
81+
var resource = "Rubberduck User Declarations - {0}";
82+
var title = string.Format(resource, DateTime.Now.ToString(CultureInfo.InvariantCulture));
83+
84+
//var textResults = title + Environment.NewLine + string.Join("", _results.Select(result => result.ToString() + Environment.NewLine).ToArray());
85+
var csvResults = ExportFormatter.Csv(aDeclarations, title, ColumnInfos);
86+
var htmlResults = ExportFormatter.HtmlClipboardFragment(aDeclarations, title, ColumnInfos);
87+
var rtfResults = ExportFormatter.RTF(aDeclarations, title);
88+
89+
MemoryStream strm1 = ExportFormatter.XmlSpreadsheetNew(aDeclarations, title, ColumnInfos);
90+
//Add the formats from richest formatting to least formatting
91+
_clipboard.AppendStream(DataFormats.GetDataFormat(XML_SPREADSHEET_DATA_FORMAT).Name, strm1);
92+
_clipboard.AppendString(DataFormats.Rtf, rtfResults);
93+
_clipboard.AppendString(DataFormats.Html, htmlResults);
94+
_clipboard.AppendString(DataFormats.CommaSeparatedValue, csvResults);
95+
//_clipboard.AppendString(DataFormats.UnicodeText, textResults);
96+
97+
_clipboard.Flush();
98+
99+
});
100+
62101
_setNameSortCommand = new DelegateCommand(param =>
63102
{
64103
SortByName = (bool)param;
@@ -138,6 +177,9 @@ public bool SortBySelection
138177
}
139178
}
140179

180+
private readonly ICommand _copyResultsCommand;
181+
public ICommand CopyResultsCommand { get { return _copyResultsCommand; } }
182+
141183
private readonly ICommand _setNameSortCommand;
142184
public ICommand SetNameSortCommand { get { return _setNameSortCommand; } }
143185

RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,14 +701,24 @@
701701
<TextBlock Text="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeExplorer_ShowDesignerToolTip}" />
702702
</Button.ToolTip>
703703
</Button>
704+
705+
<Separator />
706+
707+
<Button Command="{Binding CopyResultsCommand}">
708+
<Image Height="16" Source="../../Resources/document-copy.png" />
709+
<Button.ToolTip>
710+
<TextBlock Text="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=CodeExplorer_CopyToolTip}" />
711+
</Button.ToolTip>
712+
</Button>
713+
704714
</ToolBar>
705715
</ToolBarTray>
706716

707717
<TreeView Grid.Row="1"
708718
ItemContainerStyle="{StaticResource ShinyTreeView}"
709719
HorizontalContentAlignment="Stretch"
710720
MouseDoubleClick="TreeView_OnMouseDoubleClick"
711-
Style="{StaticResource CodeExplorerTreeViewStyle}">
721+
Style="{StaticResource CodeExplorerTreeViewStyle}" BorderThickness="0,1">
712722
<i:Interaction.Behaviors>
713723
<controls:BindableSelectedItemBehavior SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
714724
</i:Interaction.Behaviors>

RetailCoder.VBE/UI/RubberduckUI.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

RetailCoder.VBE/UI/RubberduckUI.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,9 @@ Warning: All customized settings will be lost. Your old file will be saved in '
562562
<data name="CodeExplorer_ShowFoldersToolTip" xml:space="preserve">
563563
<value>Toggle folders</value>
564564
</data>
565+
<data name="CodeExplorer_CopyToolTip" xml:space="preserve">
566+
<value>Copy to clipboard</value>
567+
</data>
565568
<data name="CodeInspections_CopyToolTip" xml:space="preserve">
566569
<value>Copy inspection results to clipboard</value>
567570
</data>

Rubberduck.Parsing/Symbols/Declaration.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,12 @@ public string ProjectName
405405
}
406406
}
407407

408+
public object[] ToArray()
409+
{
410+
return new object[] { this.ProjectName, this.CustomFolder, this.ComponentName, this.DeclarationType.ToString(), this.Scope, this.IdentifierName, this.AsTypeName };
411+
}
412+
413+
408414
/// <summary>
409415
/// Gets the name of the VBComponent the declaration is made in.
410416
/// </summary>

Rubberduck.VBEEditor/QualifiedModuleName.cs

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,86 @@ public struct QualifiedModuleName
1212
{
1313
private static string GetDisplayName(VBProject project)
1414
{
15-
if (!string.IsNullOrEmpty(Path.GetDirectoryName(project.BuildFileName)))
15+
//Try reading the filename first
16+
try
1617
{
17-
return Path.GetFileName(project.FileName);
18+
if (!string.IsNullOrEmpty(Path.GetDirectoryName(project.BuildFileName)))
19+
{
20+
return Path.GetFileName(project.FileName);
21+
}
22+
}
23+
catch
24+
{ //The GetFileName getter probably threw
25+
}
26+
27+
if (project.Protection == vbext_ProjectProtection.vbext_pp_none)
28+
{
29+
//Try reading the top-most document-type component's Properties("Name") value
30+
//Eg. A Workbook's parent is the application, so read the workbook's name
31+
try
32+
{
33+
var nameProperty = project.VBComponents.Cast<VBComponent>()
34+
.FirstOrDefault(comp => comp.Type == vbext_ComponentType.vbext_ct_Document
35+
&& comp.Properties.Item("Name").Value != null
36+
&& comp.Properties.Item("Parent")
37+
.Object.Equals(comp.Properties.Item("Application").Object))
38+
.Properties.Cast<Property>().FirstOrDefault(property => property.Name == "Name");
39+
return nameProperty == null
40+
? null
41+
: nameProperty.Value.ToString();
42+
}
43+
catch
44+
{
45+
//The Properties collection either wasn't available, or didn't have the expected properties
46+
}
47+
48+
//Try reading the top-most document-type component's parent's Properties("Name") value
49+
// Eg. A PowerPoint Slide is top level, but it's parent is a Presentation (that is NOT a vbComponent)
50+
try
51+
{
52+
var parentProp = project.VBComponents.Cast<VBComponent>()
53+
.FirstOrDefault(comp => comp.Type == vbext_ComponentType.vbext_ct_Document
54+
&& comp.Properties.Item("Parent").Value != null)
55+
.Properties.Cast<Property>().FirstOrDefault(property => property.Name == "Parent");
56+
57+
Properties props = null;
58+
Property nameProperty = null;
59+
if (parentProp.Value is Properties)
60+
{
61+
props = (Properties)parentProp.Value;
62+
nameProperty = props.Cast<Property>().FirstOrDefault(property => property.Name == "Name");
63+
}
64+
65+
return nameProperty == null
66+
? null
67+
: nameProperty.Value.ToString();
68+
}
69+
catch
70+
{
71+
//The Properties collection either wasn't available, or didn't have the expected properties
72+
}
1873
}
19-
20-
//Don't need to check protection, as a protected project is saved, by definition
21-
var firstOrDefault = project.VBComponents.Cast<VBComponent>()
22-
.Where(component => component.Type == vbext_ComponentType.vbext_ct_Document
23-
&& component.Properties.Count > 1)
24-
.SelectMany(component => component.Properties.OfType<Property>())
25-
.FirstOrDefault(property => property.Name == "Name");
26-
return firstOrDefault == null
27-
? null
28-
: firstOrDefault.Value.ToString();
74+
return null;
2975
}
3076

3177
private static string GetDisplayName(VBComponent component)
3278
{
33-
if (component.Type != vbext_ComponentType.vbext_ct_Document)
79+
if (component.Type == vbext_ComponentType.vbext_ct_Document)
3480
{
35-
return null;
81+
//Check for a valid properties collection (some hosts don't validate the Properties method unless the component's designer is open in the host
82+
try
83+
{
84+
var nameProperty = component.Properties.Item("Name");
85+
return nameProperty == null
86+
? null
87+
: nameProperty.Value.ToString();
88+
}
89+
catch
90+
{
91+
//The component isn't open in the host, the Properties Collection is probably inaccessible
92+
}
3693
}
37-
var nameProperty = component.Properties.Cast<Property>().SingleOrDefault(p => p.Name == "Name");
38-
return nameProperty == null
39-
? null
40-
: nameProperty.Value.ToString();
94+
return null;
4195
}
4296

4397
public static string GetProjectId(VBProject project)

0 commit comments

Comments
 (0)