« first day (1830 days earlier)      last day (1350 days later) » 

12:00 AM
RELOAD!
[rubberduck-vba/Rubberduck] 4 issue comments.
[Minesweeper] New Users: 14, Games Played: 74, Bombs Used: 47, Moves Performed: 10540
 
 
11 hours later…
11:17 AM
@IvenBach heh. I read that as "Reputation not found". :)
 
11:42 AM
> Integration Services supports two deployment models, the project deployment model and the legacy package deployment model. The project deployment model enables you to deploy your projects to the Integration Services server.
Since "package deployment" is legacy, I presume the preference for newly developed work would be the project deployment model?
reads on, discovers a comparison section...
further reading reinforces that the Project Deployment Model is the way to go
^ please shout if there are compelling arguments against this. I've checked and CLR has been enabled. (I'm sysadmin, so I coulda done it myself if necessary:)
We're on SQL Server 2017, so I can do incremental package deployment in case this ever manages to get way more complex. (I'm sure that in the grand scheme of things, my little package is very simple.)
 
11:58 AM
IMPOV, you don't want a complex package. All it should really do is just shove data around, and invoke some stored procedure.
Otherwise, it becomes very difficult to test your logic.
 
assumes that silence on the point implies support for using "project deployment" over "package deployment".
simplicity makes mucho senso
 
 
1 hour later…
1:27 PM
> Closes #4981

This PR already covers the scope layed out in the issue, i.e. it curently supports variable assignments on the RHS. However, I think that this is not too useful yet. So, I plan to extend the scope to new expressions, index expressions and member access expressions on the RHS.
> **Description**
Initialize function call with an open bracket "in the word"

**To Reproduce**
1. `Debug.Print "dict: " & dictToStr|this.dict`
2. Press `(`

**Expected behavior**
`Debug.Print "dict: " & dictToStr(|this.dict`
or
`Debug.Print "dict: " & dictToStr(this.dict)|`

**Resulting behavior**
`Debug.Print "dict: " & dictToStr((|); this.dict`
 
Yay!!!!!
I was having issues getting the deployment wizard to work. The answer I found at MS Community support indicated reinstalling SSDT for VS 2017, so I did.
After rebooting the machine (a required step) I fired VS back up, loaded my package et voila!
My designer now has a dark enough background when using the dark theme to show the white text!
I have no idea which version of SSDT I was on previously, but it seems that 15.1.6bajillion14 seems to have this minor, but very welcome fix.
When I added those failure lines, I didn't even know the "Failure" label was there - white on white doesn't show that well...
Now to see if the deployment wizard will actually connect to our SQL Server
 
1:46 PM
> **Description**
With MsgBox, it behaves like #4900
With Debug.Print it's different

**To Reproduce**
1. `Debug.Print |this.dc.TableName`
2. Type `"`

**Expected behavior**
`Debug.Print "|this.dc.TableName`

**Resulting behavior**
`Debug.Print ""; this.dc.TableName`
 
more success! The deployment wizard now launches. And I completed it and deployed my package. Now to test it and figure out how to pass my parameters when I call it.
 
[rubberduck-vba/Rubberduck] build for commit de99bcf0 on unknown branch: AppVeyor build succeeded
> # [Codecov](https://codecov.io/gh/rubberduck-vba/Rubberduck/pull/5003?src=pr&el=h1) Report
> Merging [#5003](https://codecov.io/gh/rubberduck-vba/Rubberduck/pull/5003?src=pr&el=desc) into [next](https://codecov.io/gh/rubberduck-vba/Rubberduck/commit/0db534ed9b63f4ff84b36baf3ae9ad89b1749486?src=pr&el=desc) will **increase** coverage by `0.05%`.
> The diff coverage is `93.33%`.


```diff
@@ Coverage Diff @@
## next #5003 +/- ##
=======================
[rubberduck-vba/Rubberduck] build for commit de99bcf0 on unknown branch: 64.28% (target 0%)
> # [Codecov](https://codecov.io/gh/rubberduck-vba/Rubberduck/pull/5003?src=pr&el=h1) Report
> Merging [#5003](https://codecov.io/gh/rubberduck-vba/Rubberduck/pull/5003?src=pr&el=desc) into [next](https://codecov.io/gh/rubberduck-vba/Rubberduck/commit/0db534ed9b63f4ff84b36baf3ae9ad89b1749486?src=pr&el=desc) will **increase** coverage by `0.05%`.
> The diff coverage is `93.33%`.


```diff
@@ Coverage Diff @@
## next #5003 +/- ##
=======================
> I'm not the expert, but I believe that is status-by-design - it's closed the `"` pair for you. It doesn't know that you want to make `this.dc.TableName` part of the string literal that you're creating by enclosing it in quotes.

My take on your **Expected behavior** is that you want SCP to be disabled if the line starts with `Debug.Print`.
 
2:04 PM
According to MS Docs:
> You create a server environment to specify runtime values for packages contained in a project you've deployed to the Integration Services server. You can then map the environment variables to parameters
Is this the only way to pass values to the parameters I've defined in my package or can I specify them by passing them in the sproc I use to launch the package (which is what I was kinda expecting).
 
2:23 PM
> This is testing the right thing - but it's also failing, and ignored/inconclusive:

https://github.com/rubberduck-vba/Rubberduck/blob/0db534ed9b63f4ff84b36baf3ae9ad89b1749486/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs#L16-L34

Ignored useful tests: 1, false negatives: 1

---

This second test is wrong - the `ActiveWorkbook` may or may not be `ThisWorkbook`. This is testing exactly the opposite of what it should, unless the code is in the `ThisWorkbook` modul
> > One problem is that setting up a mock `ThisWorkbook` document module that implements `Excel.Worksheet` isn't being done.

Not sure it *can* be done either. This might be a case where the best we can do is have a bunch of tests that ensure no false-negative situation arises, and two ignored tests document the "happy path" results-issuing code.
 
2:43 PM
> This is testing the right thing - but it's also failing, and ignored/inconclusive:

https://github.com/rubberduck-vba/Rubberduck/blob/0db534ed9b63f4ff84b36baf3ae9ad89b1749486/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs#L16-L34

Ignored useful tests: 1, false negatives: 1

---

This second test is wrong - the `ActiveWorkbook` may or may not be `ThisWorkbook`. This is testing exactly the opposite of what it should; results count should definitely be `0` in this
 
2:58 PM
i love it when my ssis package fails because something screws the pooch in the data @FreeMan
things that i have no control over
and cant account for
i swear i need to change this stupid email alert to the guy who can fix it
 
3:48 PM
This should be a more productive week.
 
@Duga actually, the typelib api can be mocked to return DocClassType.Workbook for the ThisWorkbook module; the inspection will be tweaked to take a IVBETypeLibsAPI dependency... or actually that needs to happen at the declaration resolver level.
DocumentModuleDeclaration needs to expose a DocClassType enum property
...which greatly simplifies the mock setup
...and means the inspection doesn't need to take any other dependencies
@M.Doerner the declaration resolver seems to go out of its way to avoid COM calls (which is a good thing I think) - is it going to be a problem if typelibs API calls are made here?
            case ComponentType.Document:
                return new DocumentModuleDeclaration(
                    qualifiedModuleName.QualifyMemberName(qualifiedModuleName.ComponentName),
                    projectDeclaration,
                    qualifiedModuleName.ComponentName,
                    moduleAnnotations,
                    moduleAttributes);
seems to also be a good spot to create UserFormDeclaration and leverage the typelibs API to tack-on the appropriate interfaces
 
4:04 PM
The resolver relly should not use the typeLibAPI directly. This will probably casue some problems because all calls to the typeLibAPI have to be rerouted to the UI thread.
Wasn't the original plan to use the UserComProjects for that?
 
hm, that's probably a better place, yeah
 
The basic problem there is that loading those currently does not work.
There is something strange about the type libs for user projects and I do not seel competent enough regarding COM to deal with it.
Moreover, things around this will change when, if ever, the typeLibAPI overhaul is ready and merged.
 
yeah I was looking at that PR
that's some deep, deep stuff
the IVBETypeLibsAPI interface isn't changing though
well it does, but not in a way that would break code that uses it to get the type of a document module
(ThisWorkbook)
(or of a userform/control, for that matter)
 
4:40 PM
for the record, I had emailed Wayne whether he'd give me a to-do list that he thinks is pending for the PR so we could take over. No response, so may have to cowboy it.
(that was a while ago - a bit more than 1 week ago?)
@M.Doerner Indeed; we should be calling the type API only once and early in the parse process. The downstream steps should refer to cached Com* objects. I'm a bit fuzzy if that is already done or is something we still need to do?
@MathieuGuindon If we are talking about test code in the test project (e.g. purely C#), you technically don't need Wayne's PR but rather my mocking PR (even without the support for VBA classes) to get back a mocked COM interface.
and if that is the case, then the code needs to be refactored a little more so that the mocks can be obtained for use in pure C# environment as well for VBA consumption.
You might even get away with just doing Moq.Mock<Excel.Workbook>, but you may lose the type equivalence.
 
@this yeah no at first I thought I'd take the typelib API into the inspection, but that's dumb for several reasons - one being, it's likely not going to be running on the UI thread; another being that this isn't something we want to re-do multiple times if we can help it.. best have the declarations resolver wrap up that knowledge in the DocumentModuleDeclaration
i.e. a DocumentModuleDeclaration should be able to tell us (inspection) whether it's a Workbook, a Worksheet, an AccessForm or an AccessReport
 
Yeah, you might want to just mock the Com** object if we're testing the resolver
(we might need a separate test for verifying that Com** objects are correctly provided to the resolver, not sure)
 
4:56 PM
@this To load the com projects for user projects, you currently have to set the LOAD_USER_COM_PROJECT compilarion argument.
However, please note that the actual loading does not work properly for multiple reasons.
One being that the typeLiAPI does not properly expose member and function flags and one that there is no indication whether a member is private.
There might be more issues, but I do not remember which exactly.
 
@M.Doerner but that's something we'd need to be able to, say, populate the CE tree with nodes without parsing anything, right? does it have to be a pre-requisite for getting _Workbook and _Worksheet interfaces out of ThisWorkbook and Sheet1 document modules?
basically I'm trying to get us to leverage the parts that work :)
(assuming it does work)
 
I think that is one of the few things that actually works.
You might want to test whether you can work with what is there.
 
yeah
that'll eliminate a massive amount of false positives, and close a dozen duplicate issues
 
Have a look into the ParseCoordinator to find teh exact name for the compilation constant.
I am not 100% sure it will halp with the user forms though.
 
me neither, but it can't hurt to give it a shot :)
 
5:06 PM
@M.Doerner which AIUI, we need Wayne's PR
I guess after I wrap up my own languishing PR, I could try and see if I can wrap that PR up too
needMoreTime++;
 
Thinking about it, the most appropriate place to consume the information about the base type of the document modules would be the TypeHierarchyPass.
 
@M.Doerner I have more inspection docs changes pending, that I'll have to PR tonight.. then my squeak branch has the fix for the empty modules / option explicit "bug", and I have started work on #4998 but since I haven't touched the typelibs API then none of the actual fix is in. I think I'll PR what I have (it fixes the tests, at least), if you want to implement the logic to get DocumentModuleDeclaration to expose its document type.
or I can give TypeHierarchyPass a shot, but by now you're way more familiar with it than I am
 
I wonder if we could potentially do multiple initialization passes.
For example, a bunch of our tool windows don't load any data until after at least the declaration resolve.
But I bet we could figure out ways to at least do a partial initialization with the parse tree.
Then keep adding data as we get it. Perhaps even live from the resolver passes.
 
more moving parts? :)
 
Yeah :)
An alternative idea is to bring in the idea of observable collections into the declaration structure, so, for example, we could listen for individual changes.
Instead of doing broad passes after everything is over.
 
5:16 PM
I think CE would do well w/ observable collections
 
It would potentially slow the resolve stage down, but it would sort-of speed things up a bit.
 
AIUI, reading the metadata from COM projects is wickedly fast
so we'd get the CE populated in no time
 
Stepping out for a sec quick. BBL.
 
we can then enable the other features once the resolver finish filling in other stuff.
 
5:35 PM
hi guys
 
so ive been working a bit on making classes that implement interfaces
its been going alright
im still getting a feel/ getting to a point i can be confident im building it well, but hey, im on the path at least
 
aye
the first class i built is set up to auto generate a form using the conventions that we use here for forms
the second one is designed to partially replace my save code stuff
 
6:03 PM
@this I followed the MS Docs instructions to create and map a server environment for my SSIS package. Looking at the environment properties, it says ID = 1.
I followed this STEP 2 to create the script to exec catalog.create_execution which gave me this code:
Declare @execution_id bigint
EXEC [SSISDB].[catalog].[create_execution] @package_name=N'Package.dtsx', @execution_id=@execution_id OUTPUT, @folder_name=N'Satisfaction Survey Load', @project_name=N'BizSol SatSurvey',
@use32bitruntime=False, @reference_id=null, @runinscaleout=False
which I modified slightly to use the environment ID Identified in step 1 like this:
Declare @execution_id bigint
Declare @environment_id bigint = 1		--  1 = Dev,  2 = Prod
EXEC [SSISDB].[catalog].[create_execution] @package_name=N'Package.dtsx', @execution_id=@execution_id OUTPUT, @folder_name=N'Satisfaction Survey Load', @project_name=N'BizSol SatSurvey',
@use32bitruntime=False, @reference_id=@environment_id, @runinscaleout=False
I added @environment_id (note that the comment is speculative, I'm expecting my prod environment to get #2 - if it doesn't, I'll change it)
As I understand it, I need to create an sproc with that code (and the rest of the generated code) so that I can pass in an appropriate Dev/Prod flag and set my @environment_id appropriately to determine whether which database it's running against.
Am I on the right track here?
 
> That would do. It technically is illegal since the annotation doesn't generate an attribute.
> > An option to restrict the ToDo explorer to comment lines only

@SteveLaycock This has been the case since day 1... I'm not able to get anything that isn't a comment into the todo explorer. If you have repro steps proving otherwise, please open a new issue for this.

There really isn't any restriction on what constitutes a todo marker, other than it has to match a simple regex (and be in a comment - commented-out code *is* a comment) - that's by design. I don't think we should restrict to
> > An option to restrict the ToDo explorer to comment lines only

@SteveLaycock This has been the case since day 1... I'm not able to get anything that isn't a comment into the todo explorer. If you have repro steps proving otherwise, please open a new issue for this.

There really isn't any restriction on what constitutes a todo marker, other than it has to match a simple regex (and be in a comment - commented-out code *is* a comment) - that's by design. I don't think we should restrict to
> #4617 is definitely related.

`Description` can be added to the ToDo Explorer's list of items to look for and it will list all `''@Description` lines. Unfortunately, that extra `'` comment marker in there means that the annotation parsing will, by design, ignore the `'@Description` annotation.

Either the To Do explorer needs to be expanded to pick up annotations (perhaps configurable and as requested in #4617), or there needs to be a new Annotation Explorer.
 
6:36 PM
@Duga I'm not too crazy about having an annotations exporer tbh
feels like it should be a code explorer view or something
 
@MathieuGuindon If the todo explorer can be expanded to pick up uncommented annotations, or it could be integrated into the CE, I'd be 100% with that
Just some way to find them all. Especially all the '@Ignore that I've thrown in to ignore false positives...
well, OK, there's Ctrl-F to find them, but that's... archaic, bordering on Neanderthal, what with all the other fancy-pants tools we're getting!
 
from that standpoint I'd rather expand find all references to enable right-clicking any annotation and listing all such annotations in a search results tab
right-click @Description -> shows all @Description annotations in the project
right-click @Ignore -> shows all @Ignore annotations in the project
 
that would work
 
more intuitively than via todo markers I think
and without needing yet another toolwindow
 
tbh, though, I'd like to see a list of them and be able to sort. that way I could get all @Ignore inspectionX followed by all @Ignore inspectionY. So when a fix for the false positive on inspectionX is rolled out, I can grab them all, delete them & reparse to ensure that all's well that ends well
 
6:43 PM
hm
 
that's why it's so frustrating that '@asdf is an annotation while ''@asdf is a ToDo marker and nary the twain shall meet. It's sooo close to working in the ToDo explorer, it seems like it shouldn't be a big deal to make it so, Number 1.
it may well be difficult, but it seems like it should be easy
 
definitely not 04
 
:D
 
:/
this thingy is being difficult
im doing
Public Function Create(ByRef argForm As Form) As ISaveSystem
With New SaveSystem
    Set .FormReference = argForm
    '.SaveType = ssUnset
    '.ValidationLabelStyle = mscNone
    Set Create = .Self
End With
End Function
i implemented all of the properties for the interface... and its telling me object doesnt support this property for... everything
simple test to see if it works... but it just doesnt :(
Public Sub SaveSystemTest()
Dim ss As ISaveSystem
Dim f As Form
DoCmd.OpenForm "frmSaveCodeExample", acNormal
Set f = Forms("frmSaveCodeExample")
Set ss = SaveSystem.Create(f)
Debug.Print "" 'ss2.FormReference.Controls.Count
End Sub
am i doing anything immediately stupid?
 
6:58 PM
what's ISaveSystem exposing?
 
Where exactly do you get the error?
 
uhm, well that's a breakpoint, not an error
 
the error is that when i try to access ANY property of the object
it says object doesnt support this property
 
the locals TW is borked
 
7:01 PM
but it doesnt make sense because i implemented all of the properties
well when i didnt comment out what it was doing on that debug.print, id get hte error
or maybe it works...
URGH now i look like an idiot -_-
 
nah, it's legit confusing: there's a bug in the VBE's locals toolwindow
another proof that the VBE is "actively fighting OOP" :)
 
lol
my original test was to see what would happen if i passed in a nothing
instead of a form
to determine if i needed to have error catching, but it allows a nothing.
 
I get the feeling that that bug is actually connected to how they hacked together the typelibs for VBA projects.
 
I've got my SSIS package tested & working. I deployed it and scripted catalog.create_execution to get the TSQL code to call it. Now when it executes, it gives me an error on the load from my CSV file.
 
does the account it is executing under have access/mapping to your CSV?
 
7:07 PM
I'm thinking the issue is that when the server is running it, it doesn't have access to the file, even though it's on the network - it's a share/directory that the server user can't access (passed in complete UNC to the file).
Yeah, that's what I figured.
Q: Why does it work fine when I run it from VS?
A: Because I'm running it as me, not as the SQL Server service on the server box.
^right?
OK, not an issue. I can adjust!
 
@M.Doerner that... has to be related :)
 
It works! IT WORKS!! IT WORKS!!!11!!1!1!oNe!!!!!!!!!
@MathieuGuindon - you said to let you know if I found an easier way to launch an SSIS package from VBA. I think I have.
 
By deploying with the "Project Deployment Model" instead of "Package Deployment Model" (MS Docs) and creating an environment for my Dev and Prod, this script will execute it:
 
argh. not supported in VS2015
 
7:17 PM
Declare @execution_id bigint
Declare @environment_id bigint = 1		--  1 = Dev,  2 = Prod
EXEC [SSISDB].[catalog].[create_execution] @package_name=N'Package.dtsx', @execution_id=@execution_id OUTPUT, @folder_name=N'Satisfaction Survey Load', @project_name=N'BizSol SatSurvey',
											@use32bitruntime=False, @reference_id=@environment_id, @runinscaleout=False
Select @execution_id
DECLARE @var1 smallint = 3			--level 3 = 'Verbose' good for starting, level 1 = default (minimal?)
EXEC [SSISDB].[catalog].[set_execution_parameter_value] @execution_id,  @object_type=50, @parameter_name=N'LOGGING_
> The project deployment model was introduced in SQL Server 2012 Integration Services (SSIS). With this deployment model, you were not able to deploy one or more packages without deploying the whole project. SQL Server 2016 Integration Services (SSIS) introduced the Incremental Package Deployment feature, which lets you deploy one or more packages without deploying the whole project.
oh, VS 2015 not SQL Server 2015. oops.
You sure?
 
shouldn't have to use VS for that, I think
that can be done from SSMS, too
 
if you're on a new enough version of Server, you can call sprocs to deploy instead of using a wizard that may not be in VS2015.
this does not monitor for completion, but that's reasonably trivial in either another sproc or in VBA
 
@FreeMan that doesn't look like a sproc?
 
well, it's not yet... ;)
 
oh ok. was expecting a stored procedure to kick it off.
 
7:20 PM
but those are the execution steps created by SSMS when right-click the package and selecting Execute.
 
which means you haven't yet worked on the permission problem when executing as a low user
right?
 
wrapping that in Create Procedure dbo.x... isn't difficult, nor is passing in a flag to set @environment_id as necessary.
 
dammit SSDT why do you need to open every damn package in the solution when I right-click one package
 
@this true dat.
ATM I don't care!!!! It works!!!!!
#don'trainonmyparade
 
and run every darn validation
 
7:22 PM
frankly, I'm almost happy to throw the permissions issue at our DBA - "either figure out how to set up permissions so I can run this w/o sysadmin or make me and the other guy sysadmin and live with it!"
 
@FreeMan well, I'll just wander over there and rain mainly on the plain in Spain then.</eeyore>
LOL
 
of course, with great sysadmin powers comes great sysadmin responsibility to not hose myself...
@this you go right ahead!
#JustNotHere
 
@MathieuGuindon It's Microsoft's product, so it must be super-duper helpful and friendly. Bob and Clippy shall live on forever!
 
@MathieuGuindon SS <2016, not VS 2015 issues
 
7:24 PM
right
 
well, when y'all get up to date, you've got an easier method! :)
 
@MathieuGuindon OTOH, Microsoft is also known to be very consistent.
 
cept if I was on SQL2016 I wouldn't be working SSDT in VS2015...
 
Frankly, I'm not sure if this is any easier than what you did, but with some reading it wasn't that difficult to work my way through it.
actually, I think that coming to the realization that I needed the files on a network share the server does have rights to was the most difficult part...
the rest was just dealing with the uncertainty of whether I was on the right path.
 
SQL Server 2012, VS2015, SSTD 14.0 (2013 I guess?), VSTA fires up VS2012 shell, ..#consistency
VSTA 2015
 
7:27 PM
well, ya gocher 2012, 2013, 14 & 2015, so it's at least (sorta) sequential...
 
uh-huh
I have a SQL 2014 instance too on another server, but no 2016 anywhere
 
frankly, none of this would have been possible if they hadn't just upgraded built us a new Server2016? VM with SS2016 running on it.
 
:quack:
 
@mansellan yo!
 
@mansellan bless you!
 
7:39 PM
> @retailcoder My mistake. I didn't check properly and made the assumption that the err.description was NOT in a commented out line.
 
@MathieuGuindon Uh, I can't even follow the PR description lol
 
8:42 PM
> I'm retagging this as enhancement because the resulting behaviour is the current designed status. The suggestion to change the autocompletion behaviour could have some merit, but I wouldn't classify this as a bug...
 
8:58 PM
> @daFreeMan is correct; SCP is doing its job and auto-closes `""` the double-quotes for you, not knowing the intent is to later go to the end of the expression and `"` close the string.

Debug.Print "" something

The above would be illegal; the semicolon is inserted by the VBE to make the expression legal:

Debug.Print ""; something

There's a `//todo` comment somewhere in the SCP code, to make it "wrap" the selection, so you would have this:

Debug.Print [something here]
 
^R#'s autocompletion is doing the same thing.
i.e. it never wraps anything.
 
is that something worth doing though?
 
Personally, I would be surprised every time.
 
I think it could be useful for bracketing
but yeah
surprised like "oh!" or surprised like "huh?"
;-)
 
Like, where did my closing quotes go?
I would not expect them somewhere to the right of my focus.
 
9:05 PM
but if your [focus] is a multi-character selection, like, you had to explicitly go and make that selection
 
With focus, I mean the place I am looking at.
 
I mean you have [focus] selected, hit " and you get "focus"
 
Arrgh! Excel, why do you have to keep crashing when inserting Japanese characters into a cell?
 
or hit ( and you get (focus)
 
@M.Doerner because its racist
 
9:07 PM
nah, more like it's less and less stable with every darn release
 
I have to be careful to only insert into the text when the cell is opened and not immediately.
I guess, it might also have something to do with the area I am working in having a query attached, which I never wanted.
I just wanted to import something from a tsv file.
Why does that have to imply attaching some query?
 
9:25 PM
@M.Doerner IIRC, it's a setting in R#.
I don't have it anymore, though, so I can't double-check :)
I do know it does it for braces.
 
I'd make it a (disabled by default) setting, too
I think it (wrapping) is a reasonable work-around for the "insert SCP opener char here but don't close it because I want to close it at the end of the instruction"
vs. arbitrarily bailing out depending on what the left-of-caret content is
 
10:17 PM
you know, its funny, i never realized that VS didnt have a line control built in
like access does
 
@KySoto not VS; WinForms
IIRC in MSForms with VS6 you had line controls
Not sure if it was from the toolbox or if I drew them programmatically, but I clarly remember making etched lines by drawing a 1px white line on top of a 2px gray line
 

« first day (1830 days earlier)      last day (1350 days later) »