1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using System . Linq ;
3
4
using System . IO ;
4
5
using Microsoft . Vbe . Interop ;
@@ -21,48 +22,62 @@ public static class VBComponentExtensions
21
22
public static string ExportAsSourceFile ( this VBComponent component , string directoryPath )
22
23
{
23
24
var path = Path . Combine ( directoryPath , component . Name + component . Type . FileExtension ( ) ) ;
24
- if ( component . Type == vbext_ComponentType . vbext_ct_Document )
25
+ switch ( component . Type )
25
26
{
26
- var lineCount = component . CodeModule . CountOfLines ;
27
- if ( lineCount > 0 )
28
- {
29
- var text = component . CodeModule . get_Lines ( 1 , lineCount ) ;
30
- File . WriteAllText ( path , text ) ;
31
- }
27
+ case vbext_ComponentType . vbext_ct_MSForm :
28
+ ExportUserFormModule ( component , path ) ;
29
+ break ;
30
+ case vbext_ComponentType . vbext_ct_Document :
31
+ ExportDocumentModule ( component , path ) ;
32
+ break ;
33
+ default :
34
+ component . Export ( path ) ;
35
+ break ;
32
36
}
33
- else if ( component . Type == vbext_ComponentType . vbext_ct_MSForm )
37
+
38
+ return path ;
39
+ }
40
+
41
+ private static void ExportUserFormModule ( VBComponent component , string path )
42
+ {
43
+ // VBIDE API inserts an extra newline when exporting a UserForm module.
44
+ // this issue causes forms to always be treated as "modified" in source control, which causes conflicts.
45
+ // we need to remove the extra newline before the file gets written to its output location.
46
+
47
+ var visibleCode = component . CodeModule . Lines ( ) . Split ( new [ ] { Environment . NewLine } , StringSplitOptions . None ) ;
48
+ var legitEmptyLineCount = visibleCode . TakeWhile ( string . IsNullOrWhiteSpace ) . Count ( ) ;
49
+
50
+ var tempFile = component . ExportToTempFile ( ) ;
51
+ var contents = File . ReadAllLines ( tempFile ) ;
52
+ var nonAttributeLines = contents . TakeWhile ( line => ! line . StartsWith ( "Attribute" ) ) . Count ( ) ;
53
+ var attributeLines = contents . Skip ( nonAttributeLines ) . TakeWhile ( line => line . StartsWith ( "Attribute" ) ) . Count ( ) ;
54
+ var declarationsStartLine = nonAttributeLines + attributeLines + 1 ;
55
+
56
+ var emptyLineCount = contents . Skip ( declarationsStartLine - 1 )
57
+ . TakeWhile ( string . IsNullOrWhiteSpace )
58
+ . Count ( ) ;
59
+
60
+ var code = contents ;
61
+ if ( emptyLineCount > legitEmptyLineCount )
34
62
{
35
- // VBIDE API inserts an extra newline when exporting a UserForm module.
36
- // this issue causes forms to always be treated as "modified" in source control, which causes conflicts.
37
- // we need to remove the extra newline before the file gets written to its output location.
38
- var tempFile = component . ExportToTempFile ( ) ;
39
- var contents = File . ReadAllLines ( tempFile ) ;
40
- var vbExposedAttributeLine = 0 ;
41
- for ( var i = 0 ; i < contents . Length ; i ++ )
42
- {
43
- if ( contents [ i ] . StartsWith ( "Attribute VB_Exposed = " ) )
44
- {
45
- vbExposedAttributeLine = i ;
46
- break ;
47
- }
48
- }
49
- if ( contents . Length > vbExposedAttributeLine && contents [ vbExposedAttributeLine + 1 ] . Replace ( Environment . NewLine , string . Empty ) . Trim ( ) == string . Empty )
50
- {
51
- // first line in module is empty - assume it wasn't in the VBE
52
- var edited = contents . Take ( vbExposedAttributeLine ) . Union ( contents . Skip ( vbExposedAttributeLine + 1 ) ) . ToArray ( ) ;
53
- File . WriteAllLines ( path , edited ) ;
54
- }
63
+ code = contents . Take ( declarationsStartLine ) . Union (
64
+ contents . Skip ( declarationsStartLine + emptyLineCount - legitEmptyLineCount ) )
65
+ . ToArray ( ) ;
55
66
}
56
- else
67
+ File . WriteAllLines ( path , code ) ;
68
+ }
69
+
70
+ private static void ExportDocumentModule ( VBComponent component , string path )
71
+ {
72
+ var lineCount = component . CodeModule . CountOfLines ;
73
+ if ( lineCount > 0 )
57
74
{
58
- // other module types can just be exported directly
59
- component . Export ( path ) ;
75
+ var text = component . CodeModule . Lines [ 1 , lineCount ] ;
76
+ File . WriteAllText ( path , text ) ;
60
77
}
61
-
62
- return path ;
63
78
}
64
79
65
- public static string ExportToTempFile ( this VBComponent component )
80
+ private static string ExportToTempFile ( this VBComponent component )
66
81
{
67
82
var path = Path . Combine ( Path . GetTempPath ( ) , component . Name + component . Type . FileExtension ( ) ) ;
68
83
component . Export ( path ) ;
0 commit comments