From dbdoug at gmail.com Tue May 1 13:17:25 2018 From: dbdoug at gmail.com (Doug Steele) Date: Tue, 1 May 2018 15:17:25 -0300 Subject: [AccessD] Payroll In-Reply-To: <5AE79093.3657.4BEA278B@stuart.lexacorp.com.pg> References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com> <00fb01d3e0b1$5e365a90$1aa30fb0$@gmail.com> <5AE79093.3657.4BEA278B@stuart.lexacorp.com.pg> Message-ID: I've build time tracking databases both ways - either using the normalized simple 'atomic' time records, or by using pay period based records. I don't know which to recommend. All I know is that, as soon as you use pay period based records, you will be asked to build reports by date range, not pay period range, but as soon as you use the simple records, you'll need to build screens and reports based on pay periods. Basically, you're going to have to write code to convert one type to the other and back, no matter what - take your pick! Doug On Mon, Apr 30, 2018 at 6:54 PM, Stuart McLachlan wrote: > At times, there are valid reasons for NOT normalising or for re-thinking > what you actual mean > by nromalisation. > > This is one of them. > > Think in terms of a TYPE or Object called a "PayPeriod" rather than "Day" > and D1Hours to > D14Hours become separate attributes, not separate entities. :) > > I've built systems exactly like this in the past and in fact I'm doing > another one right now. > > I doubt that there will ever be a fortnight with more or less days. :) > > If they decide to change to a different pay period, (weekly or monthly?) > how you store daily > attendance hours will be the least of your worries. > > > > On 30 Apr 2018 at 11:30, Bob Heygood wrote: > > > Rocky & Jim, > > Yes I knew intuitively that I was breaking some normalization rules. > > Just started to let the UI interface drive the schema. > > > > For data entry the user insists on being able to "tab" through a whole > > pay period (2 weeks) for each employee and job. > > > > So, how do I use a table with only one record per day? > > UNBOUND, I guess. And then via code stuff into a "proper" > > table........ I have done so before but a lot work. > > > > Really don't need any other fields. > > > > Thanks for responding, > > > > Bob > > > > > > > > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > From dbdoug at gmail.com Tue May 1 13:21:33 2018 From: dbdoug at gmail.com (Doug Steele) Date: Tue, 1 May 2018 15:21:33 -0300 Subject: [AccessD] Payroll In-Reply-To: <5AE79093.3657.4BEA278B@stuart.lexacorp.com.pg> References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com> <00fb01d3e0b1$5e365a90$1aa30fb0$@gmail.com> <5AE79093.3657.4BEA278B@stuart.lexacorp.com.pg> Message-ID: One other thing I add from (bitter) experience is that, when you build a time tracking system base on some kind of period (daily, weekly, monthly, bi-monthly, bi-weekly), give some though to what you would need to do to your code if the time period suddenly changes! Doug On Mon, Apr 30, 2018 at 6:54 PM, Stuart McLachlan wrote: > At times, there are valid reasons for NOT normalising or for re-thinking > what you actual mean > by nromalisation. > > This is one of them. > > Think in terms of a TYPE or Object called a "PayPeriod" rather than "Day" > and D1Hours to > D14Hours become separate attributes, not separate entities. :) > > I've built systems exactly like this in the past and in fact I'm doing > another one right now. > > I doubt that there will ever be a fortnight with more or less days. :) > > If they decide to change to a different pay period, (weekly or monthly?) > how you store daily > attendance hours will be the least of your worries. > > > > On 30 Apr 2018 at 11:30, Bob Heygood wrote: > > > Rocky & Jim, > > Yes I knew intuitively that I was breaking some normalization rules. > > Just started to let the UI interface drive the schema. > > > > For data entry the user insists on being able to "tab" through a whole > > pay period (2 weeks) for each employee and job. > > > > So, how do I use a table with only one record per day? > > UNBOUND, I guess. And then via code stuff into a "proper" > > table........ I have done so before but a lot work. > > > > Really don't need any other fields. > > > > Thanks for responding, > > > > Bob > > > > > > > > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > From jimdettman at verizon.net Tue May 1 14:42:03 2018 From: jimdettman at verizon.net (Jim Dettman) Date: Tue, 1 May 2018 15:42:03 -0400 Subject: [AccessD] Payroll In-Reply-To: References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com> <00fb01d3e0b1$5e365a90$1aa30fb0$@gmail.com> <5AE79093.3657.4BEA278B@stuart.lexacorp.com.pg> Message-ID: <06db01d3e184$7af9cbc0$70ed6340$@verizon.net> That's why I'd rather go for the detail and summarize Plus, you never know when and what else you'll be asked to track. What if someone takes a half day off for jury duty? Jim. -----Original Message----- From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Doug Steele Sent: Tuesday, May 1, 2018 2:22 PM To: Access Developers discussion and problem solving Subject: Re: [AccessD] Payroll One other thing I add from (bitter) experience is that, when you build a time tracking system base on some kind of period (daily, weekly, monthly, bi-monthly, bi-weekly), give some though to what you would need to do to your code if the time period suddenly changes! Doug On Mon, Apr 30, 2018 at 6:54 PM, Stuart McLachlan wrote: > At times, there are valid reasons for NOT normalising or for re-thinking > what you actual mean > by nromalisation. > > This is one of them. > > Think in terms of a TYPE or Object called a "PayPeriod" rather than "Day" > and D1Hours to > D14Hours become separate attributes, not separate entities. :) > > I've built systems exactly like this in the past and in fact I'm doing > another one right now. > > I doubt that there will ever be a fortnight with more or less days. :) > > If they decide to change to a different pay period, (weekly or monthly?) > how you store daily > attendance hours will be the least of your worries. > > > > On 30 Apr 2018 at 11:30, Bob Heygood wrote: > > > Rocky & Jim, > > Yes I knew intuitively that I was breaking some normalization rules. > > Just started to let the UI interface drive the schema. > > > > For data entry the user insists on being able to "tab" through a whole > > pay period (2 weeks) for each employee and job. > > > > So, how do I use a table with only one record per day? > > UNBOUND, I guess. And then via code stuff into a "proper" > > table........ I have done so before but a lot work. > > > > Really don't need any other fields. > > > > Thanks for responding, > > > > Bob > > > > > > > > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com From jamesbutton at blueyonder.co.uk Tue May 1 15:52:05 2018 From: jamesbutton at blueyonder.co.uk (James Button) Date: Tue, 1 May 2018 21:52:05 +0100 Subject: [AccessD] Payroll In-Reply-To: <06db01d3e184$7af9cbc0$70ed6340$@verizon.net> References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com> <00fb01d3e0b1$5e365a90$1aa30fb0$@gmail.com> <5AE79093.3657.4BEA278B@stuart.lexacorp.com.pg> <06db01d3e184$7af9cbc0$70ed6340$@verizon.net> Message-ID: Or, as happened to me - Had to take a 2 hour break from a shift to report to the police that my car had been broken into and accompany them to the car, (in the works car park during working time - the heated rear window smashed!) Then, the following day another 90 minutes to have the replacement window put into the car. OK - I could have taken the rest of the day off, but that would have seriously annoyed my employer as it would have meant at least 8 hours delay to the already late project I was working on! Yes - that was optional as the employer could have said I could not take time off from a shift. That would mean I missed an entire shift. - But court attendance - not optional! Not as a juror, or as a witness JimB -----Original Message----- From: AccessD On Behalf Of Jim Dettman Sent: Tuesday, May 1, 2018 8:42 PM To: 'Access Developers discussion and problem solving' Subject: Re: [AccessD] Payroll That's why I'd rather go for the detail and summarize Plus, you never know when and what else you'll be asked to track. What if someone takes a half day off for jury duty? Jim. -----Original Message----- From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Doug Steele Sent: Tuesday, May 1, 2018 2:22 PM To: Access Developers discussion and problem solving Subject: Re: [AccessD] Payroll One other thing I add from (bitter) experience is that, when you build a time tracking system base on some kind of period (daily, weekly, monthly, bi-monthly, bi-weekly), give some though to what you would need to do to your code if the time period suddenly changes! Doug On Mon, Apr 30, 2018 at 6:54 PM, Stuart McLachlan wrote: > At times, there are valid reasons for NOT normalising or for re-thinking > what you actual mean > by nromalisation. > > This is one of them. > > Think in terms of a TYPE or Object called a "PayPeriod" rather than "Day" > and D1Hours to > D14Hours become separate attributes, not separate entities. :) > > I've built systems exactly like this in the past and in fact I'm doing > another one right now. > > I doubt that there will ever be a fortnight with more or less days. :) > > If they decide to change to a different pay period, (weekly or monthly?) > how you store daily > attendance hours will be the least of your worries. > > > > On 30 Apr 2018 at 11:30, Bob Heygood wrote: > > > Rocky & Jim, > > Yes I knew intuitively that I was breaking some normalization rules. > > Just started to let the UI interface drive the schema. > > > > For data entry the user insists on being able to "tab" through a whole > > pay period (2 weeks) for each employee and job. > > > > So, how do I use a table with only one record per day? > > UNBOUND, I guess. And then via code stuff into a "proper" > > table........ I have done so before but a lot work. > > > > Really don't need any other fields. > > > > Thanks for responding, > > > > Bob > > > > > > > > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com From stuart at lexacorp.com.pg Tue May 1 16:17:31 2018 From: stuart at lexacorp.com.pg (Stuart McLachlan) Date: Wed, 02 May 2018 07:17:31 +1000 Subject: [AccessD] Payroll In-Reply-To: References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com>, <06db01d3e184$7af9cbc0$70ed6340$@verizon.net>, Message-ID: <5AE8D96B.2253.50EEB3CD@stuart.lexacorp.com.pg> On 1 May 2018 at 21:52, James Button via AccessD wrote: > Or, as happened to me - > Had to take a 2 hour break from a shift to report to the police that > my car had been broken into and accompany them to the car, (in the > works car park during working time - the heated rear window smashed!) > Then, the following day another 90 minutes to have the replacement > window put into the car. > > OK - I could have taken the rest of the day off, but that would have > seriously annoyed my employer as it would have meant at least 8 hours > delay to the already late project I was working on! > > Yes - that was optional as the employer could have said I could not > take time off from a shift. That would mean I missed an entire shift. > - But court attendance - not optional! Not as a juror, or as a witness > > JimB > > > > -----Original Message----- > From: AccessD On Behalf Of Jim > Dettman Sent: Tuesday, May 1, 2018 8:42 PM To: 'Access Developers > discussion and problem solving' > Subject: Re: [AccessD] Payroll > > > That's why I'd rather go for the detail and summarize > > Plus, you never know when and what else you'll be asked to track. > What if > someone takes a half day off for jury duty? > > Jim. > > -----Original Message----- > From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf > Of Doug Steele Sent: Tuesday, May 1, 2018 2:22 PM To: Access > Developers discussion and problem solving Subject: Re: [AccessD] > Payroll > > One other thing I add from (bitter) experience is that, when you build > a time tracking system base on some kind of period (daily, weekly, > monthly, bi-monthly, bi-weekly), give some though to what you would > need to do to your code if the time period suddenly changes! > > Doug > > On Mon, Apr 30, 2018 at 6:54 PM, Stuart McLachlan > wrote: > > > At times, there are valid reasons for NOT normalising or for > > re-thinking what you actual mean by nromalisation. > > > > This is one of them. > > > > Think in terms of a TYPE or Object called a "PayPeriod" rather than > > "Day" and D1Hours to D14Hours become separate attributes, not > > separate entities. :) > > > > I've built systems exactly like this in the past and in fact I'm > > doing another one right now. > > > > I doubt that there will ever be a fortnight with more or less days. > > :) > > > > If they decide to change to a different pay period, (weekly or > > monthly?) how you store daily attendance hours will be the least of > > your worries. > > > > > > > > On 30 Apr 2018 at 11:30, Bob Heygood wrote: > > > > > Rocky & Jim, > > > Yes I knew intuitively that I was breaking some normalization > > > rules. Just started to let the UI interface drive the schema. > > > > > > For data entry the user insists on being able to "tab" through a > > > whole pay period (2 weeks) for each employee and job. > > > > > > So, how do I use a table with only one record per day? > > > UNBOUND, I guess. And then via code stuff into a "proper" > > > table........ I have done so before but a lot work. > > > > > > Really don't need any other fields. > > > > > > Thanks for responding, > > > > > > Bob > > > > > > > > > > > > > > > -- > > AccessD mailing list > > AccessD at databaseadvisors.com > > http://databaseadvisors.com/mailman/listinfo/accessd > > Website: http://www.databaseadvisors.com > > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > From stuart at lexacorp.com.pg Tue May 1 16:17:32 2018 From: stuart at lexacorp.com.pg (Stuart McLachlan) Date: Wed, 02 May 2018 07:17:32 +1000 Subject: [AccessD] Payroll In-Reply-To: References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com>, <06db01d3e184$7af9cbc0$70ed6340$@verizon.net>, Message-ID: <5AE8D96C.13671.50EEB42B@stuart.lexacorp.com.pg> Assuming an 8 hour work day, that's just 6 hrs on day 1 and 6.5 hours on day 2. How/where you track the reasons for absences is an entrely different topic to how you recordhours worked. Let's not complicate the issue unnecessarily, Bob said ealier: "I should have been a bit more clear. I am only tracking the hours worked per day per payperiod." On 1 May 2018 at 21:52, James Button via AccessD wrote: > Or, as happened to me - > Had to take a 2 hour break from a shift to report to the police that > my car had been broken into and accompany them to the car, (in the > works car park during working time - the heated rear window smashed!) > Then, the following day another 90 minutes to have the replacement > window put into the car. > > OK - I could have taken the rest of the day off, but that would have > seriously annoyed my employer as it would have meant at least 8 hours > delay to the already late project I was working on! > > Yes - that was optional as the employer could have said I could not > take time off from a shift. That would mean I missed an entire shift. > - But court attendance - not optional! Not as a juror, or as a witness > > JimB > From jamesbutton at blueyonder.co.uk Tue May 1 17:34:11 2018 From: jamesbutton at blueyonder.co.uk (James Button) Date: Tue, 1 May 2018 23:34:11 +0100 Subject: [AccessD] Payroll In-Reply-To: <5AE8D96C.13671.50EEB42B@stuart.lexacorp.com.pg> References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com>, <06db01d3e184$7af9cbc0$70ed6340$@verizon.net>, <5AE8D96C.13671.50EEB42B@stuart.lexacorp.com.pg> Message-ID: I was under the impression that the specification was to record a single start time and a single end time for any day So - in the case of my incident having worked for a couple of hours before being interrupted to deal with the car, that would mean about 6 hours worked for the 2 shifts Note - shifts of at least 10 hours a day on that job! Usually 7am to 7 pm less, maybe, occasionally an hour lunch break. And the point being that specification is not only, not a good approach, but it is probably deeply flawed! JimB -----Original Message----- From: AccessD On Behalf Of Stuart McLachlan Sent: Tuesday, May 1, 2018 10:18 PM To: Access Developers discussion and problem solving Subject: Re: [AccessD] Payroll Assuming an 8 hour work day, that's just 6 hrs on day 1 and 6.5 hours on day 2. How/where you track the reasons for absences is an entrely different topic to how you recordhours worked. Let's not complicate the issue unnecessarily, Bob said ealier: "I should have been a bit more clear. I am only tracking the hours worked per day per payperiod." On 1 May 2018 at 21:52, James Button via AccessD wrote: > Or, as happened to me - > Had to take a 2 hour break from a shift to report to the police that > my car had been broken into and accompany them to the car, (in the > works car park during working time - the heated rear window smashed!) > Then, the following day another 90 minutes to have the replacement > window put into the car. > > OK - I could have taken the rest of the day off, but that would have > seriously annoyed my employer as it would have meant at least 8 hours > delay to the already late project I was working on! > > Yes - that was optional as the employer could have said I could not > take time off from a shift. That would mean I missed an entire shift. > - But court attendance - not optional! Not as a juror, or as a witness > > JimB > -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com From accesspro at gmail.com Wed May 2 17:36:50 2018 From: accesspro at gmail.com (Bob Heygood) Date: Wed, 2 May 2018 15:36:50 -0700 Subject: [AccessD] Payroll In-Reply-To: <5AE8D96C.13671.50EEB42B@stuart.lexacorp.com.pg> References: <0a3101d3de3b$47d9a900$d78cfb00$@gmail.com>, <06db01d3e184$7af9cbc0$70ed6340$@verizon.net>, <5AE8D96C.13671.50EEB42B@stuart.lexacorp.com.pg> Message-ID: <026001d3e266$10bbc8c0$32335a40$@gmail.com> Thanks Stuart, Again, sorry if I did not state objective clearly. Pay periods are in stone. I know, we have all heard this before. NO time of day is involved. Just a matter of recording hours worked ( straight, time and a half and double time) for a given job and pay period; for a given employee. I am pretty sure I will stick with my original schema unless I run into an issue. Only non "normalized" aspect is multiple date fields in the time card table. Thanks again all Bob -----Original Message----- From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Stuart McLachlan Sent: Tuesday, May 1, 2018 2:18 PM To: Access Developers discussion and problem solving Subject: Re: [AccessD] Payroll Assuming an 8 hour work day, that's just 6 hrs on day 1 and 6.5 hours on day 2. How/where you track the reasons for absences is an entrely different topic to how you recordhours worked. Let's not complicate the issue unnecessarily, Bob said ealier: "I should have been a bit more clear. I am only tracking the hours worked per day per payperiod." On 1 May 2018 at 21:52, James Button via AccessD wrote: > Or, as happened to me - > Had to take a 2 hour break from a shift to report to the police that > my car had been broken into and accompany them to the car, (in the > works car park during working time - the heated rear window smashed!) > Then, the following day another 90 minutes to have the replacement > window put into the car. > > OK - I could have taken the rest of the day off, but that would have > seriously annoyed my employer as it would have meant at least 8 hours > delay to the already late project I was working on! > > Yes - that was optional as the employer could have said I could not > take time off from a shift. That would mean I missed an entire shift. > - But court attendance - not optional! Not as a juror, or as a witness > > JimB > -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com From gustav at cactus.dk Fri May 4 04:03:24 2018 From: gustav at cactus.dk (Gustav Brock) Date: Fri, 4 May 2018 09:03:24 +0000 Subject: [AccessD] Converting Imperial measures In-Reply-To: References: Message-ID: Hi all I realised that it takes a little more to do this properly. So, I took my rounding functions - which are for decimals, of course, thus for Base 10 numbers - and modified it for Base 2 rounding. The reason is, that you need to convert between decimals (like 0.125) and fractions (like 1/8). For many values, there will be no exact conversion, thus you need high precision for reliable results. That can be achieved by using Decimal. You'll find a detailed description here: "Round by the power of two" https://www.experts-exchange.com/articles/31859/Round-by-the-power-of-two.html So much for the calculation. What's missing, is to parse and format the imperial expressions. Again, this is not as simple as one may think, indeed not if you wish to have generic functions that will cover just about any read-world scenario. The functions can be found here: "Convert and format imperial distance (feet and inches) with high precision" https://www.experts-exchange.com/articles/31931/Convert-and-format-imperial-distance-feet-and-inches-with-high-precision.html All code - which is tested for both Access and Excel - can be found at GitHub: https://github.com/GustavBrock/VBA.Round.git Please let me now if you see anything that needs a correction. /gustav ________________________________________ Fra: AccessD p? vegne af Gustav Brock Sendt: 21. februar 2018 09:59:15 Til: Access Developers discussion and problem solving Emne: Re: [AccessD] Converting Imperial measures Hi all And yes a small addition ("+0") to also accept Null values and empty strings and return zero for these: DecimalFeet = Eval(Replace(Replace(Replace(Replace("+0" & m, """", ""), "'", "*12 "), " ", "+"), "-", "+")) / 12 /gustav -----Oprindelig meddelelse----- Fra: AccessD [mailto:accessd-bounces at databaseadvisors.com] P? vegne af Gustav Brock Sendt: 16. februar 2018 16:38 Til: Access Developers discussion and problem solving Emne: Re: [AccessD] Converting Imperial measures Hi all One more Replace is needed to accept strings with a dash like 8' 5-7/16": DecimalFeet = Eval(Replace(Replace(Replace(Replace(m, """", ""), "'", "*12 "), " ", "+"), "-", "+")) / 12 When DO the US enter modern time and switch to decimals? /gustav -----Oprindelig meddelelse----- Fra: AccessD [mailto:accessd-bounces at databaseadvisors.com] P? vegne af Gustav Brock Sendt: 16. februar 2018 15:59 Til: Access Developers discussion and problem solving Emne: [AccessD] Converting Imperial measures Hi all Good examples for usage of Eval are rare, but here is one - a one-liner for converting Imperial feet-inch measures (string) to decimal feet (double): DecimalFeet = Eval(Replace(Replace(Replace([Measurement], """", ""), "'", "*12 "), " ", "+")) / 12 It will accept expressions like: 6' 7" 7 3/4" 6'7" 6' 7" 6' 5 3/16" /gustav From gustav at cactus.dk Fri May 4 09:28:22 2018 From: gustav at cactus.dk (Gustav Brock) Date: Fri, 4 May 2018 14:28:22 +0000 Subject: [AccessD] Unlock/Unprotect VBA Project Message-ID: Hi all This was new to me: Open a ?protected? VBE project in minutes: Open the db in the Hex Editor of your choosing and replace any DPB= with DPX=, then use SaveAs ?. Open the newly created db, go into the VBE (you?ll get error messages, just dismiss them), go into the project properties and set a new password, save, close, reopen and all is good! https://www.devhut.net/2018/05/03/access-unlocking-an-access-vba-project/ The same is true for Excel, ? /gustav From jimdettman at verizon.net Fri May 4 10:07:59 2018 From: jimdettman at verizon.net (Jim Dettman) Date: Fri, 4 May 2018 11:07:59 -0400 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: References: Message-ID: <01f401d3e3b9$b15ccbe0$141663a0$@verizon.net> Yeah, that one has actually been out there a while :( Found it somewhere a couple years back. Suffice to say, the only real way left to protect your code is with a MDE. Wayne is the only one I know of that can pull source text from VBA p-code and he's adamant about proof of ownership. Jim. -----Original Message----- From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Gustav Brock Sent: Friday, May 4, 2018 10:28 AM To: Access Developers discussion and problem solving Subject: [AccessD] Unlock/Unprotect VBA Project Hi all This was new to me: Open a ?protected? VBE project in minutes: Open the db in the Hex Editor of your choosing and replace any DPB= with DPX=, then use SaveAs ?. Open the newly created db, go into the VBE (you?ll get error messages, just dismiss them), go into the project properties and set a new password, save, close, reopen and all is good! https://www.devhut.net/2018/05/03/access-unlocking-an-access-vba-project/ The same is true for Excel, ? /gustav -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com From df.waters at outlook.com Fri May 4 10:26:21 2018 From: df.waters at outlook.com (Dan Waters) Date: Fri, 4 May 2018 15:26:21 +0000 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: <01f401d3e3b9$b15ccbe0$141663a0$@verizon.net> References: <01f401d3e3b9$b15ccbe0$141663a0$@verizon.net> Message-ID: I wish there was an MDE equivalent for a Windows Forms app. Dan -----Original Message----- From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Jim Dettman Sent: May 4, 2018 10:08 To: 'Access Developers discussion and problem solving' Subject: Re: [AccessD] Unlock/Unprotect VBA Project Yeah, that one has actually been out there a while :( Found it somewhere a couple years back. Suffice to say, the only real way left to protect your code is with a MDE. Wayne is the only one I know of that can pull source text from VBA p-code and he's adamant about proof of ownership. Jim. -----Original Message----- From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Gustav Brock Sent: Friday, May 4, 2018 10:28 AM To: Access Developers discussion and problem solving Subject: [AccessD] Unlock/Unprotect VBA Project Hi all This was new to me: Open a ?protected? VBE project in minutes: Open the db in the Hex Editor of your choosing and replace any DPB= with DPX=, then use SaveAs ?. Open the newly created db, go into the VBE (you?ll get error messages, just dismiss them), go into the project properties and set a new password, save, close, reopen and all is good! https://www.devhut.net/2018/05/03/access-unlocking-an-access-vba-project/ The same is true for Excel, ? /gustav -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com From bensonforums at gmail.com Sun May 6 20:33:42 2018 From: bensonforums at gmail.com (Bill Benson) Date: Sun, 6 May 2018 21:33:42 -0400 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: References: Message-ID: You might want to look into making a project "Unviewable" . There are some (extremely few) limitations on this utility, but it is pretty solid. The authors are very current on security matters, and very willing to engage in discussions. While I could use a $13 piece of software to export all of the vba modules out of a workbook, I did find a means of hiding all connection strings, passwords, etc in a userform control's text or tag properties. It is virtually impossible to force that userform into a loaded state to read those crucial strings, from an external workbook, unless I the author of the protected workbook was foolish enough to have a public sub that loaded them, therefore it was virtually impossible to get access to that protected information. I can't recommend this product highly enough, and I don't think there is any way to defeat it without a combination of sloppy programming and some kind of tool that would be so sophisticated that probably whoever possessed it would be very reluctant to make it commercially available. On Fri, May 4, 2018 at 10:28 AM, Gustav Brock wrote: > Hi all > > This was new to me: Open a ?protected? VBE project in minutes: > > Open the db in the Hex Editor of your choosing and replace any DPB= with > DPX=, then use SaveAs ?. Open the newly created db, go into the VBE > (you?ll get error messages, just dismiss them), go into the project > properties and set a new password, save, close, reopen and all is good! > > https://www.devhut.net/2018/05/03/access-unlocking-an-access-vba-project/ > > The same is true for Excel, ? > > /gustav > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > From stuart at lexacorp.com.pg Sun May 6 22:05:36 2018 From: stuart at lexacorp.com.pg (Stuart McLachlan) Date: Mon, 07 May 2018 13:05:36 +1000 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: References: , Message-ID: <5AEFC280.28532.6BED2B6A@stuart.lexacorp.com.pg> If you are that concerned about application security, you shouldn't be storing passwords at all. Store a cryptographic hash and then compare the hash of the entered password to the stored hash. Same with usernames. On 6 May 2018 at 21:33, Bill Benson wrote: > I did find a means of hiding all connection strings, passwords, etc in > a userform control's text or tag properties. It is virtually > impossible to force that userform into a loaded state to read those > crucial strings, from an external workbook, unless I the author of the > protected workbook was foolish enough to have a public sub that loaded > them, therefore it was virtually impossible to get access to that > protected information. From bensonforums at gmail.com Sun May 6 22:37:28 2018 From: bensonforums at gmail.com (Bill Benson) Date: Mon, 07 May 2018 03:37:28 +0000 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: <5AEFC280.28532.6BED2B6A@stuart.lexacorp.com.pg> References: <5AEFC280.28532.6BED2B6A@stuart.lexacorp.com.pg> Message-ID: Stuart, Can you demonstrat that storing them in the manner I proposed, together with an "unviewable +" locked project exposes this information, in any possible way -other than perhaps reading internal memory, which would be WAY WAY WAY over my head to figure out how to do? Without a public function in the target workbook which exposes them, do you have any method of getting at that info? On Sun, May 6, 2018, 11:06 PM Stuart McLachlan wrote: > If you are that concerned about application security, you shouldn't be > storing passwords at > all. Store a cryptographic hash and then compare the hash of the entered > password to the > stored hash. Same with usernames. > > On 6 May 2018 at 21:33, Bill Benson wrote: > > > I did find a means of hiding all connection strings, passwords, etc in > > a userform control's text or tag properties. It is virtually > > impossible to force that userform into a loaded state to read those > > crucial strings, from an external workbook, unless I the author of the > > protected workbook was foolish enough to have a public sub that loaded > > them, therefore it was virtually impossible to get access to that > > protected information. > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > From stuart at lexacorp.com.pg Mon May 7 00:45:37 2018 From: stuart at lexacorp.com.pg (Stuart McLachlan) Date: Mon, 07 May 2018 15:45:37 +1000 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: References: , <5AEFC280.28532.6BED2B6A@stuart.lexacorp.com.pg>, Message-ID: <5AEFE801.16502.6C7FAAAA@stuart.lexacorp.com.pg> ISTM that if the actual connection strings, passwords etc are "stored" anywhere in the application, be it a form's text or tag property or anywhere else, then opening the file in a hex viewer is likely to reveal them. On 7 May 2018 at 3:37, Bill Benson wrote: > Stuart, > > Can you demonstrat that storing them in the manner I proposed, > together with an "unviewable +" locked project exposes this > information, in any possible way -other than perhaps reading internal > memory, which would be WAY WAY WAY over my head to figure out how to > do? Without a public function in the target workbook which exposes > them, do you have any method of getting at that info? > > On Sun, May 6, 2018, 11:06 PM Stuart McLachlan > wrote: > > > If you are that concerned about application security, you shouldn't > > be storing passwords at all. Store a cryptographic hash and then > > compare the hash of the entered password to the stored hash. Same > > with usernames. > > > > On 6 May 2018 at 21:33, Bill Benson wrote: > > > > > I did find a means of hiding all connection strings, passwords, > > > etc in a userform control's text or tag properties. It is > > > virtually impossible to force that userform into a loaded state to > > > read those crucial strings, from an external workbook, unless I > > > the author of the protected workbook was foolish enough to have a > > > public sub that loaded them, therefore it was virtually impossible > > > to get access to that protected information. > > > > -- > > AccessD mailing list > > AccessD at databaseadvisors.com > > http://databaseadvisors.com/mailman/listinfo/accessd > > Website: http://www.databaseadvisors.com > > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > From bensonforums at gmail.com Mon May 7 18:24:53 2018 From: bensonforums at gmail.com (Bill Benson) Date: Mon, 7 May 2018 19:24:53 -0400 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: <5AEFE801.16502.6C7FAAAA@stuart.lexacorp.com.pg> References: <5AEFC280.28532.6BED2B6A@stuart.lexacorp.com.pg> <5AEFE801.16502.6C7FAAAA@stuart.lexacorp.com.pg> Message-ID: I wrote to the author of Unviewable+... He wrote back that not all of the vba project is stored in text form (my note: he did not specify which parts are or aren't). What is readable in a hex editor kind of depends - mostly driven by the simplicity of the compression algorithm, especially if not random text. He allows that an advanced and determined hacker could decompress the entire VBA project using special software and compromise the intellectual property. I'll just add my two bits, that this can be partially mitigated by obfuscating the code, spreading out passwords across several seemingly garbldy-gook function calls, with strings spread across multiple forms and controls in their text properties... it would take an awfully determined and advanced hacker to crack this mechanism. As for dealing with hashes in general, I know nothing of how to do that. I rest my (perhaps weak) case at this point. Cheers! On Mon, May 7, 2018 at 1:45 AM, Stuart McLachlan wrote: > ISTM that if the actual connection strings, passwords etc are "stored" > anywhere in the > application, be it a form's text or tag property or anywhere else, then > opening the file in a hex > viewer is likely to reveal them. > > > On 7 May 2018 at 3:37, Bill Benson wrote: > > > Stuart, > > > > Can you demonstrat that storing them in the manner I proposed, > > together with an "unviewable +" locked project exposes this > > information, in any possible way -other than perhaps reading internal > > memory, which would be WAY WAY WAY over my head to figure out how to > > do? Without a public function in the target workbook which exposes > > them, do you have any method of getting at that info? > > > > On Sun, May 6, 2018, 11:06 PM Stuart McLachlan > > wrote: > > > > > If you are that concerned about application security, you shouldn't > > > be storing passwords at all. Store a cryptographic hash and then > > > compare the hash of the entered password to the stored hash. Same > > > with usernames. > > > > > > On 6 May 2018 at 21:33, Bill Benson wrote: > > > > > > > I did find a means of hiding all connection strings, passwords, > > > > etc in a userform control's text or tag properties. It is > > > > virtually impossible to force that userform into a loaded state to > > > > read those crucial strings, from an external workbook, unless I > > > > the author of the protected workbook was foolish enough to have a > > > > public sub that loaded them, therefore it was virtually impossible > > > > to get access to that protected information. > > > > > > -- > > > AccessD mailing list > > > AccessD at databaseadvisors.com > > > http://databaseadvisors.com/mailman/listinfo/accessd > > > Website: http://www.databaseadvisors.com > > > > > -- > > AccessD mailing list > > AccessD at databaseadvisors.com > > http://databaseadvisors.com/mailman/listinfo/accessd > > Website: http://www.databaseadvisors.com > > > > > -- > AccessD mailing list > AccessD at databaseadvisors.com > http://databaseadvisors.com/mailman/listinfo/accessd > Website: http://www.databaseadvisors.com > From stuart at lexacorp.com.pg Mon May 7 19:39:28 2018 From: stuart at lexacorp.com.pg (Stuart McLachlan) Date: Tue, 08 May 2018 10:39:28 +1000 Subject: [AccessD] Unlock/Unprotect VBA Project In-Reply-To: References: , <5AEFE801.16502.6C7FAAAA@stuart.lexacorp.com.pg>, Message-ID: <5AF0F1C0.2737.708DBE3F@stuart.lexacorp.com.pg> On 7 May 2018 at 19:24, Bill Benson wrote: > As for dealing with hashes in general, I know nothing of how to do that. A bit of plug-and-play boilerplate for storing passwords with SHA1 See https://tools.ietf.org/html/rfc3174 While it's not the most secure of hashes and you will see internet alarmism about it being broken and not to use it, it's more than secure enough for most purposes. Save credentials: Currentdb.Execute "Insert into tblUsers (Username,PW) Values ('" & txtUsername & "','" & hashstring(txtPassword) & "');" Validate credentials: If hashstring(txtPassword) <> DLookup("PW","tblUsers","Username = '" & txtusername & "'") then Msgbox "Invalid username or password!" The Hashstring stored and compared will always be a 40 hex character string. It would take a determined hacker a looong time to find out what password to enter to match the stored PW value: 3ED8250971CC5F536E7FD7E086EE7EA970896CEB modCrypto (watch for wordwrap) Option Explicit Option Compare Database Private Type FourBytes A As Byte B As Byte C As Byte D As Byte End Type Private Type OneLong L As Long End Type Function hashString(str As String) As String Dim B() As Byte B = StrConv(str, vbFromUnicode) hashString = HexDefaultSHA1(B) End Function Function HexDefaultSHA1(Message() As Byte) As String Dim H1 As Long, H2 As Long, H3 As Long, H4 As Long, H5 As Long DefaultSHA1 Message, H1, H2, H3, H4, H5 HexDefaultSHA1 = DecToHex5(H1, H2, H3, H4, H5) End Function Sub DefaultSHA1(Message() As Byte, H1 As Long, H2 As Long, H3 As Long, H4 As Long, H5 As Long) xSHA1 Message, &H5A827999, &H6ED9EBA1, &H8F1BBCDC, &HCA62C1D6, H1, H2, H3, H4, H5 End Sub Sub xSHA1(Message() As Byte, ByVal Key1 As Long, ByVal Key2 As Long, ByVal Key3 As Long, ByVal Key4 As Long, H1 As Long, H2 As Long, H3 As Long, H4 As Long, H5 As Long) Dim U As Long, P As Long Dim FB As FourBytes, OL As OneLong Dim i As Integer Dim W(80) As Long Dim A As Long, B As Long, C As Long, D As Long, E As Long Dim T As Long H1 = &H67452301: H2 = &HEFCDAB89: H3 = &H98BADCFE: H4 = &H10325476: H5 = &HC3D2E1F0 U = UBound(Message) + 1: OL.L = U32ShiftLeft3(U): A = U \ &H20000000: LSet FB = OL 'U32ShiftRight29(U) ReDim Preserve Message(0 To (U + 8 And -64) + 63) Message(U) = 128 U = UBound(Message) Message(U - 4) = A Message(U - 3) = FB.D Message(U - 2) = FB.C Message(U - 1) = FB.B Message(U) = FB.A While P < U For i = 0 To 15 FB.D = Message(P) FB.C = Message(P + 1) FB.B = Message(P + 2) FB.A = Message(P + 3) LSet OL = FB W(i) = OL.L P = P + 4 Next i For i = 16 To 79 W(i) = U32RotateLeft1(W(i - 3) Xor W(i - 8) Xor W(i - 14) Xor W(i - 16)) Next i A = H1: B = H2: C = H3: D = H4: E = H5 For i = 0 To 19 T = U32Add(U32Add(U32Add(U32Add(U32RotateLeft5(A), E), W(i)), Key1), ((B And C) Or ((Not B) And D))) E = D: D = C: C = U32RotateLeft30(B): B = A: A = T Next i For i = 20 To 39 T = U32Add(U32Add(U32Add(U32Add(U32RotateLeft5(A), E), W(i)), Key2), (B Xor C Xor D)) E = D: D = C: C = U32RotateLeft30(B): B = A: A = T Next i For i = 40 To 59 T = U32Add(U32Add(U32Add(U32Add(U32RotateLeft5(A), E), W(i)), Key3), ((B And C) Or (B And D) Or (C And D))) E = D: D = C: C = U32RotateLeft30(B): B = A: A = T Next i For i = 60 To 79 T = U32Add(U32Add(U32Add(U32Add(U32RotateLeft5(A), E), W(i)), Key4), (B Xor C Xor D)) E = D: D = C: C = U32RotateLeft30(B): B = A: A = T Next i H1 = U32Add(H1, A): H2 = U32Add(H2, B): H3 = U32Add(H3, C): H4 = U32Add(H4, D): H5 = U32Add(H5, E) Wend End Sub Function U32Add(ByVal A As Long, ByVal B As Long) As Long If (A Xor B) < 0 Then U32Add = A + B Else U32Add = (A Xor &H80000000) + B Xor &H80000000 End If End Function Function U32ShiftLeft3(ByVal A As Long) As Long U32ShiftLeft3 = (A And &HFFFFFFF) * 8 If A And &H10000000 Then U32ShiftLeft3 = U32ShiftLeft3 Or &H80000000 End Function Function U32ShiftRight29(ByVal A As Long) As Long U32ShiftRight29 = (A And &HE0000000) \ &H20000000 And 7 End Function Function U32RotateLeft1(ByVal A As Long) As Long U32RotateLeft1 = (A And &H3FFFFFFF) * 2 If A And &H40000000 Then U32RotateLeft1 = U32RotateLeft1 Or &H80000000 If A And &H80000000 Then U32RotateLeft1 = U32RotateLeft1 Or 1 End Function Function U32RotateLeft5(ByVal A As Long) As Long U32RotateLeft5 = (A And &H3FFFFFF) * 32 Or (A And &HF8000000) \ &H8000000 And 31 If A And &H4000000 Then U32RotateLeft5 = U32RotateLeft5 Or &H80000000 End Function Function U32RotateLeft30(ByVal A As Long) As Long U32RotateLeft30 = (A And 1) * &H40000000 Or (A And &HFFFC) \ 4 And &H3FFFFFFF If A And 2 Then U32RotateLeft30 = U32RotateLeft30 Or &H80000000 End Function Function DecToHex5(ByVal H1 As Long, ByVal H2 As Long, ByVal H3 As Long, ByVal H4 As Long, ByVal H5 As Long) As String Dim H As String, L As Long DecToHex5 = "0000000000000000000000000000000000000000" H = Hex(H1): L = Len(H): Mid(DecToHex5, 9 - L, L) = H H = Hex(H2): L = Len(H): Mid(DecToHex5, 17 - L, L) = H H = Hex(H3): L = Len(H): Mid(DecToHex5, 25 - L, L) = H H = Hex(H4): L = Len(H): Mid(DecToHex5, 33 - L, L) = H H = Hex(H5): L = Len(H): Mid(DecToHex5, 41 - L, L) = H End Function From rockysmolin at bchacc.com Fri May 11 10:58:31 2018 From: rockysmolin at bchacc.com (Rocky Smolin) Date: Fri, 11 May 2018 08:58:31 -0700 Subject: [AccessD] Word Automation Question Message-ID: <002701d3e940$e8f363c0$bada2b40$@bchacc.com> Dear Lists: I have a client who wants to merge data from a record into form letters (these are legal documents). So I decided to use bookmarks which seemed to be going OK at first. But he First Name/Middle Initial/Last Name combo appears in more than one place and apparently each occurrence of that combo needs to call out different bookmark names - that is, when I add First Name as a second bookmark it disappears from the first bookmark. Obviously not the right way to do this. Can anyone point me in the right direction here? MTIA Rocky Smolin Beach Access Software 760-683-5777 www.bchacc.com www.e-z-mrp.com Skype: rocky.smolin From jimdettman at verizon.net Fri May 11 11:46:46 2018 From: jimdettman at verizon.net (Jim Dettman) Date: Fri, 11 May 2018 12:46:46 -0400 Subject: [AccessD] Word Automation Question In-Reply-To: <002701d3e940$e8f363c0$bada2b40$@bchacc.com> References: <002701d3e940$e8f363c0$bada2b40$@bchacc.com> Message-ID: <00fd01d3e947$a69663e0$f3c32ba0$@verizon.net> I have some very old code for pushing data into bookmarks from the Access side. I know JC took that and added to it for something he was doing. Shouldn't take much though to bring it up to date. Was straight forward enough. The main function is below. I'll send you the DB in a minute. Jim. Function AutomateWord(ByVal varMergeName As Variant, ByVal strProcessFlag As String, Optional ByVal fDestroyObject As Variant) As Integer ' Purpose: ' Based on the data stored in tblAuto, tblAutoFields, and tblAutoParams, ' this function use Automation to control Word, ' It inserts data into a document (varWordDoc) and prints the document. ' This is completely driven by the tblAuto, tblAutoFields, and tblAutoParams tables. ' (This function was originally written to use DDE.) ' In: ' varWordDoc = name of Word document ' fOneRec = use first record only, even if multiple records in query ' fDestroyObject = set object variable to Nothing when done ' Out: ' Return value: True if successful; False if failure ' History: ' Created 11/10/94 pel; Last Modified 04/20/97 pel ' Updated 03/10/98 Jrd - Added tblAutoParams and new arguments. ' Updated 05/29/98 JRD - Forced word to not background print. ' If background printing on, timing issues resulted. On Error GoTo AutomateWordErr Dim db As Database Dim rstHeader As Recordset Dim rstFields As Recordset Dim rstParams As Recordset Dim rstData As Recordset Dim varWordDocName As Variant Dim varQueryName As Variant Dim prmName As Parameter Dim qdfData As QueryDef Dim varDocAndPath As Variant Dim varPreprocessFunction As Variant Dim varQueryParameter As Variant Dim varSendFields As Variant Dim varDocPrint As Variant Dim varDocMacroPrint As Variant Dim varCopies As Variant Dim varReturn As Variant Dim intI As Integer Dim intJ As Integer Dim fOneRec As Integer ' 32-bit version follows Dim avarFields As Variant ' 16-bit version follows 'Dim avarFields() As Variant ' Next two lines needed for 16-bit version only 'Dim intFieldsRecCnt As Integer 'Dim intFieldsFldLim As Integer Dim intFieldsRecLim As Integer Const strProc = "AutomateWord" Const pelMaxFields = 25 Const pelQuote = """" Const pelFldWWBookmark = 0 Const pelFldAccessField = 1 Const pelFldWWFont = 2 Const pelFldWWPoints = 3 Const pelFldWWBold = 4 Const pelFldWWItalics = 5 Const pelFldWWUnderline = 6 Const pelWordMacroRun = 1 Const pelWordFileCloseNoSave = 2 ' Set process options Select Case strProcessFlag Case "P" ' If preview mode. fOneRec = True varDocPrint = False Case "T" ' Test print fOneRec = True varDocPrint = True Case Else ' Assume normal print fOneRec = False varDocPrint = True End Select ' optional parameters only work in 32-bit land If IsMissing(fDestroyObject) Then fDestroyObject = True AutomateWord = False Set db = CurrentDb() Set rstHeader = db.OpenRecordset("select * from tblAutoHeader where [MergeName] = " & pelQuote & varMergeName & pelQuote, dbOpenSnapshot, dbForwardOnly) If rstHeader.RecordCount < 1 Then MsgBox "Can't continue because tblAutoHeader record not found.", vbCritical + vbOKOnly, strProc GoTo AutomateWordDone End If ' Grab information from header record varWordDocName = rstHeader!WWDocument varQueryName = rstHeader!QueryName varPreprocessFunction = rstHeader!PreProcessFunction varSendFields = rstHeader!SendFields varDocMacroPrint = rstHeader!DocMacroPrint varCopies = rstHeader!DocCopies rstHeader.Close ' Perform pre-process function if required If Not IsNull(varPreprocessFunction) Then varReturn = Eval(varPreprocessFunction) If Not varReturn Then MsgBox "Cannot continue because preprocess failed.", vbCritical + vbOKOnly, strProc GoTo AutomateWordDone End If End If ' Grab field information Set rstFields = db.OpenRecordset("Select WWBookmark, AccessField, WWFont, WWPoints, WWBold, WWItalics, WWUnderline From tblAutoFields Where [MergeName] = " & pelQuote & varMergeName & pelQuote, dbOpenSnapshot) If rstFields.RecordCount < 1 Then MsgBox "Error: no tblAutoFields records were found.", vbCritical + vbOKOnly, strProc GoTo AutomateWordDone End If ' The following only works in 32-bit Access ' Use GetRows method to fill avarFields array ' with the records from tblAutoFields avarFields = rstFields.GetRows(pelMaxFields) intFieldsRecLim = UBound(avarFields, 2) + 1 ' But in 16-bit world, we'll have to move through ' the field records one at a time ' *** beginning of 16-bit code *** 'rstFields.MoveLast 'intFieldsRecLim = rstFields.RecordCount 'intFieldsFldLim = rstFields.Fields.Count 'ReDim avarFields(0 To intFieldsFldLim, 0 To intFieldsRecLim) 'intFieldsRecCnt = 0 'rstFields.MoveFirst 'Do While Not rstFields.EOF ' For intI = 0 To intFieldsFldLim - 1 ' avarFields(intI, intFieldsRecCnt) = rstFields.Fields(intI) ' Next intI ' intFieldsRecCnt = intFieldsRecCnt + 1 ' rstFields.MoveNext 'Loop ' *** end of 16-bit code *** rstFields.Close '32-bit only If intFieldsRecLim = pelMaxFields Then MsgBox "Warning: maximum number of fields reached.", vbInformation + vbOKOnly, strProc End If ' Begin Automation conversation with Word ' Don't need to intialize mobjWord if it already points to Word If mobjWord Is Nothing Then On Error Resume Next Set mobjWord = GetObject(, "Word.Basic") If Err <> 0 Then Err = 0 Set mobjWord = CreateObject("Word.Basic") End If If Err <> 0 Then MsgBox "Error: Word Automation object could not be created.", vbCritical + vbOKOnly, strProc GoTo AutomateWordDone End If On Error GoTo AutomateWordErr End If ' Make sure background printing is turned off. mobjWord.ToolsOptionsPrint , , , , , , , , , 0 ' Open querydef and set parameters if necessary. Set qdfData = db.QueryDefs(varQueryName) Set rstParams = db.OpenRecordset("Select * From tblAutoParams Where [MergeName] = " & pelQuote & varMergeName & pelQuote, dbOpenSnapshot) For intI = 0 To qdfData.PARAMETERS.Count - 1 Set prmName = qdfData.PARAMETERS(intI) rstParams.FindFirst "MergeName = '" & varMergeName & "' AND ParamName = '" & prmName.Name & "'" If rstParams.NoMatch Then MsgBox "Can't continue because value for parameter '" & prmName.Name & "' is not in tblAutoParams.", vbCritical + vbOKOnly, strProc GoTo AutomateWordDone Else prmName.Value = Eval(rstParams![ParamValue]) End If Next intI rstParams.Close Set rstParams = Nothing ' Create data recordset Set rstData = qdfData.OpenRecordset(dbOpenSnapshot, dbForwardOnly) If rstData.RecordCount < 1 Then MsgBox "Can't continue because no records returned by '" & varQueryName & "' query.", vbCritical + vbOKOnly, strProc GoTo AutomateWordDone End If ' Docment is located in current database directory. varDocAndPath = GetDBDir() & varWordDocName ' Create a new document for each data record. Do While Not rstData.EOF mobjWord.FileOpen varDocAndPath ' Send data, if any, over to document and format it If varSendFields Then ' Move through tblAutoFields row by row ' and send over data to document For intJ = 0 To intFieldsRecLim - 1 ' Jump to bookmark mobjWord.EditGoto avarFields(pelFldWWBookmark, intJ) 'mobjWord.Selection.Goto What:=wdGoToBookmark, Name:=avarFields(pelFldWWBookmark, intJ) ' Format the font per field specification mobjWord.FormatFont avarFields(pelFldWWPoints, intJ), IIf(avarFields(pelFldWWUnderline, intJ), 1, 0), , , , , , , , , , , , , , avarFields(pelFldWWFont, intJ), IIf(avarFields(pelFldWWBold, intJ), 1, 0), IIf(avarFields(pelFldWWItalics, intJ), 1, 0) ' Insert the data at the bookmark mobjWord.INSERT pelNullToZLS(rstData(avarFields(pelFldAccessField, intJ))) Next intJ End If ' varSendFields Debug.Print "Loaded and formatted data for " & rstData.[Name] ' Print the document, if required ' Otherwise shift focus to document for user edit If varDocPrint Then ' Print the document if required ' Use a Print Macro if one has been specified DoEvents If IsNull(varDocMacroPrint) Then mobjWord.FilePrint , , , , , , , pelNullToZLS(varCopies) Else mobjWord.ToolsMacro varDocMacroPrint, pelWordMacroRun End If Debug.Print "Printed document" End If DoEvents DoEvents If varDocPrint Then mobjWord.FileClose pelWordFileCloseNoSave Debug.Print "Executed File Close" DoEvents DoEvents End If ' If requested as one record only, ' it's time to bail out! If fOneRec Then Exit Do Else rstData.MoveNext End If Loop rstData.Close Set rstData = Nothing If fOneRec And Not varDocPrint Then ' Now shift focus to Word mobjWord.AppShow AppActivate "Microsoft Word - " & varWordDocName Else AppActivate "Microsoft Access" End If AutomateWord = True AutomateWordDone: On Error Resume Next If fDestroyObject Then Set mobjWord = Nothing If Not rstHeader Is Nothing Then rstHeader.Close If Not rstFields Is Nothing Then rstFields.Close If Not rstData Is Nothing Then rstData.Close If Not rstParams Is Nothing Then rstData.Close On Error GoTo 0 Exit Function AutomateWordErr: DoCmd.Hourglass False Select Case Err Case Else MsgBox "Error#" & Err & ": " & Error, vbCritical + vbOKOnly, "AutomateWord" End Select Resume AutomateWordDone End Function -----Original Message----- From: AccessD [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Rocky Smolin Sent: Friday, May 11, 2018 11:59 AM To: 'Access Developers discussion and problem solving'; 'Off Topic' Subject: [AccessD] Word Automation Question <> From jwcolby at gmail.com Thu May 17 01:14:55 2018 From: jwcolby at gmail.com (John Colby) Date: Thu, 17 May 2018 02:14:55 -0400 Subject: [AccessD] Filesystemobject and sql server In-Reply-To: References: Message-ID: <9508e9ef-a931-4e64-de3a-021569560467@Gmail.com> Kevin, I don't think so but I am copying the list for other opinions. When you convert to a SQL Server database, the data can be put in one or many different database files.? In any case, the SQL Server engine creates the database files and as long as they are mounted they are locked by the SQL Server engine. 1) The SQL Server engine can make copies of the database file(s) but the copies are in the SQL Server file formats.? It can also make backups of the files which are different from copies. 2) AFAIK no, the SQL Server engine cannot directly create a copy of the data in the MDB format. The sql server engine can be manipulated by VBA.? It is very inefficient and I don't recommend it but it can be done.? I did so for awhile but I ended up learning C# and using that to do the SQL Server automation. The problem with doing the automation in VBA is that VBA is single threaded which means that when a SQL Server operation begins, the thread in VBA is locked and control doesn't return to your app until SQL Server finishes whatever it is doing.? In C# you can have threads.? You can assign a thread to perform an operation, you can even spin off multiple threads and use each one to have the engine doing various things simultaneously.? And have a thread dedicated to your user interface so that the form (or whatever the UI is) doesn't lock up. All that said, if all you want to do is run queries and reports from Access using SQL Server as a BE, that will work just fine within the restraints mentioned above.? If you ask for a stored procedure or query to hand back a data set, that will happen.? If it happens to take 10 minutes your users will be frustrated because it appears that Access has locked up.? But it does work.? And the truth is that SQL Server often can do things in seconds that Access and JET would take minutes or hours to do natively.? So it is worth looking at / doing.? And sometimes a database just gets so big that the MDB route no longer works. On 5/17/2018 12:08 AM, Kevin Roberts wrote: > Hi John, > I see your posts on the AccessD forum and I wonder if you know the > answer to my newbie questions: > I have a split Access db both mdb format and use filesystemobject > Copyfile command in VBA to make a copy of the backend mdb. > I'm planning to migrate the backend mdb to SQL server but keep the > Access front end. Will the filesystem object command still work after > migrating the backend to SQL server? > 1.Can I use it to create a clone of the SQL server back end ? > 2. Can I use it to convert the SQL server back-end tables to a copy of > the backend in the mdb format? > > Thanks > Kevin > > > Sent from ProtonMail mobile > > -- John W. Colby From accessd at shaw.ca Thu May 17 11:30:33 2018 From: accessd at shaw.ca (Jim Lawrence) Date: Thu, 17 May 2018 10:30:33 -0600 (MDT) Subject: [AccessD] Filesystemobject and sql server In-Reply-To: <9508e9ef-a931-4e64-de3a-021569560467@Gmail.com> References: <9508e9ef-a931-4e64-de3a-021569560467@Gmail.com> Message-ID: <760675635.20783949.1526574633986.JavaMail.zimbra@shaw.ca> Excellent. Would you have some C# code examples showing how you separate out activies via threads? Jim ----- Original Message ----- From: "John Colby" To: "Kevin Roberts" , "Access Developers discussion and problem solving" Sent: Wednesday, May 16, 2018 11:14:55 PM Subject: Re: [AccessD] Filesystemobject and sql server Kevin, I don't think so but I am copying the list for other opinions. When you convert to a SQL Server database, the data can be put in one or many different database files.? In any case, the SQL Server engine creates the database files and as long as they are mounted they are locked by the SQL Server engine. 1) The SQL Server engine can make copies of the database file(s) but the copies are in the SQL Server file formats.? It can also make backups of the files which are different from copies. 2) AFAIK no, the SQL Server engine cannot directly create a copy of the data in the MDB format. The sql server engine can be manipulated by VBA.? It is very inefficient and I don't recommend it but it can be done.? I did so for awhile but I ended up learning C# and using that to do the SQL Server automation. The problem with doing the automation in VBA is that VBA is single threaded which means that when a SQL Server operation begins, the thread in VBA is locked and control doesn't return to your app until SQL Server finishes whatever it is doing.? In C# you can have threads.? You can assign a thread to perform an operation, you can even spin off multiple threads and use each one to have the engine doing various things simultaneously.? And have a thread dedicated to your user interface so that the form (or whatever the UI is) doesn't lock up. All that said, if all you want to do is run queries and reports from Access using SQL Server as a BE, that will work just fine within the restraints mentioned above.? If you ask for a stored procedure or query to hand back a data set, that will happen.? If it happens to take 10 minutes your users will be frustrated because it appears that Access has locked up.? But it does work.? And the truth is that SQL Server often can do things in seconds that Access and JET would take minutes or hours to do natively.? So it is worth looking at / doing.? And sometimes a database just gets so big that the MDB route no longer works. On 5/17/2018 12:08 AM, Kevin Roberts wrote: > Hi John, > I see your posts on the AccessD forum and I wonder if you know the > answer to my newbie questions: > I have a split Access db both mdb format and use filesystemobject > Copyfile command in VBA to make a copy of the backend mdb. > I'm planning to migrate the backend mdb to SQL server but keep the > Access front end. Will the filesystem object command still work after > migrating the backend to SQL server? > 1.Can I use it to create a clone of the SQL server back end ? > 2. Can I use it to convert the SQL server back-end tables to a copy of > the backend in the mdb format? > > Thanks > Kevin > > > Sent from ProtonMail mobile > > -- John W. Colby -- AccessD mailing list AccessD at databaseadvisors.com http://databaseadvisors.com/mailman/listinfo/accessd Website: http://www.databaseadvisors.com From rockysmolin at bchacc.com Sat May 19 22:20:15 2018 From: rockysmolin at bchacc.com (Rocky Smolin) Date: Sat, 19 May 2018 20:20:15 -0700 Subject: [AccessD] fms Message-ID: <017801d3efe9$79380810$6ba81830$@bchacc.com> Does anyone have any experience with the FMS screen resizer? If so, what was it? TIA Rocky