Access custom Increment ("yy" & 0000) [duplicate] - ms-access

I am working on an Access 2013 database that will have different utility poles entered into the database and linked with other attributes. Each pole will have a unique global ID, and to simplify working I would like to add another unique ID that is more simple. I would like this field auto populated when a new pole in imported into the database. The ID would go as follows:
SAC(year)-(Escalating number, cannot be a duplicate)
ex. SAC16-20 (This would be the 20th pole entered into the database in 2016)
ex. SAC15-2536 (Would be the 2536th pole entered in 2015)
If anyone could help me generate some code to make this auto populate ID field work I would greatly appreciate it.

With Access versions 2010 and later you can use an event-driven data macro to generate the sequential ID. For example, say you have a table named [poledata]. Open it in Design View and add two fields:
alternate_id_seq – Numeric (Long Integer)
alternate_id – Text(20)
Save the changes to your table and then switch to Datasheet View.
In the Access ribbon, switch to the "Table Tools > Table" tab and click "Before Change"
then enter the following macro ...
... or paste the following XML into the macro editor window
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="BeforeChange">
<Statements>
<ConditionalBlock>
<If>
<Condition>[IsInsert]</Condition>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">next_seq</Argument>
<Argument Name="Value">1</Argument>
</Action>
<Action Name="SetLocalVar">
<Argument Name="Name">prefix</Argument>
<Argument Name="Value">"SAC" & Year(Date()) Mod 100 & "-"</Argument>
</Action>
<LookUpRecord>
<Data Alias="pd">
<Query>
<References>
<Reference Source="poledata" Alias="pd" />
</References>
<Results>
<Property Source="pd" Name="alternate_id_seq" />
</Results>
<Ordering>
<Order Direction="Descending" Source="pd" Name="alternate_id_seq" />
</Ordering>
</Query>
<WhereCondition>[pd].[alternate_id] Like [prefix] & "*"</WhereCondition>
</Data>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">next_seq</Argument>
<Argument Name="Value">[pd].[alternate_id_seq]+1</Argument>
</Action>
</Statements>
</LookUpRecord>
<Action Name="SetField">
<Argument Name="Field">alternate_id_seq</Argument>
<Argument Name="Value">[next_seq]</Argument>
</Action>
<Action Name="SetField">
<Argument Name="Field">alternate_id</Argument>
<Argument Name="Value">[prefix] & [next_seq]</Argument>
</Action>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</DataMacro>
</DataMacros>
Now when new rows are added to the table the [alternate_id_seq] and [alternate_id] columns will be populated automatically.

Related

Access data macro get value from query (auto numbering)

Instead of the using the auto number in Access (sometimes produces duplicates) I've decided to generate my own numbers.
I am using the data macro Before Change but I'm not sure on how to run the query SELECT MAX(ID)+1 FROM MyTable and insert it into the ID field on each Insert.
I've messed around with the SetField, SetLocalVar, LookUpRecord actions but no luck so far.
EDIT: I've tried using DMAX in the expression as per example: https://www.599cd.com/tips/access/incrementing-your-own-counter/. This works when I add a row manually. However, I add rows from Excel VBA at which point this method stops working, generating the error, the function is not valid for expressions used in data macros
You can only use very limited SQL statements in data macros. You can use queries, though.
Create a query (called QueryA), and enter SELECT MAX(ID)+1 As Expr1 FROM MyTable as the SQL
Then, you can use a data macro with the following structure:
If [IsInsert] Then
Look Up A Record In QueryA
SetLocalVar
Name = NewID
Expression = [QueryA].[Expr1]
SetField
Name = ID
Value = NewID
The AXL is the following:
<?xml version="1.0" encoding="UTF-8"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="BeforeChange">
<Statements>
<ConditionalBlock>
<If>
<Condition>[IsInsert]</Condition>
<Statements>
<LookUpRecord>
<Data>
<Reference>QueryA</Reference>
</Data>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">NewID</Argument>
<Argument Name="Value">[QueryA].[Expr1]</Argument>
</Action>
</Statements>
</LookUpRecord>
<Action Name="SetField">
<Argument Name="Field">Field1</Argument>
<Argument Name="Value">[NewID]</Argument>
</Action>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</DataMacro>
</DataMacros>
You shouldn't use VBA functions or domain aggregates such as DMax in data macros, nor in the queries data macros are dependent upon. If you do, it can only be triggered from a running Access application, because these are only valid from within Access.
Alternatively, you can rewrite your SQL statement to be valid for data macros. This means: no aggregates, no calculations! But you can use ordering to get the maximum value:
If [IsInsert] Then
Look Up A Record In SELECT [MyTable].[ID] As [Expr1] FROM [MyTable] ORDER BY [MyTable].[ID] DESC
Alias A
SetLocalVar
Name = NewID
Expression = [A].[Expr1] + 1
SetField
Name = ID
Value = NewID
The AXL is the following (which makes it easier to understand the limited SQL):
<?xml version="1.0" encoding="UTF-8"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="BeforeChange">
<Statements>
<ConditionalBlock>
<If>
<Condition>[IsInsert]</Condition>
<Statements>
<LookUpRecord>
<Data Alias="A">
<Query>
<References>
<Reference Source="MyTable" />
</References>
<Results>
<Property Source="MyTable" Name="ID" Alias="Expr1" />
</Results>
<Ordering>
<Order Direction="Descending" Source="MyTable" Name="ID" />
</Ordering>
</Query>
</Data>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">NewID</Argument>
<Argument Name="Value">[A].[Expr1]+1</Argument>
</Action>
<Action Name="SetField">
<Argument Name="Field">Field1</Argument>
<Argument Name="Value">[NewID]</Argument>
</Action>
</Statements>
</LookUpRecord>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</DataMacro>
</DataMacros>
Replaces Access Autonumber LongInt Data Type Using simple Data Macro and one simple VBA function (see images x2)
Data Macro
VBA Code

How to autoincrease PO number , and link it to my main table? [duplicate]

I am working on an Access 2013 database that will have different utility poles entered into the database and linked with other attributes. Each pole will have a unique global ID, and to simplify working I would like to add another unique ID that is more simple. I would like this field auto populated when a new pole in imported into the database. The ID would go as follows:
SAC(year)-(Escalating number, cannot be a duplicate)
ex. SAC16-20 (This would be the 20th pole entered into the database in 2016)
ex. SAC15-2536 (Would be the 2536th pole entered in 2015)
If anyone could help me generate some code to make this auto populate ID field work I would greatly appreciate it.
With Access versions 2010 and later you can use an event-driven data macro to generate the sequential ID. For example, say you have a table named [poledata]. Open it in Design View and add two fields:
alternate_id_seq – Numeric (Long Integer)
alternate_id – Text(20)
Save the changes to your table and then switch to Datasheet View.
In the Access ribbon, switch to the "Table Tools > Table" tab and click "Before Change"
then enter the following macro ...
... or paste the following XML into the macro editor window
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="BeforeChange">
<Statements>
<ConditionalBlock>
<If>
<Condition>[IsInsert]</Condition>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">next_seq</Argument>
<Argument Name="Value">1</Argument>
</Action>
<Action Name="SetLocalVar">
<Argument Name="Name">prefix</Argument>
<Argument Name="Value">"SAC" & Year(Date()) Mod 100 & "-"</Argument>
</Action>
<LookUpRecord>
<Data Alias="pd">
<Query>
<References>
<Reference Source="poledata" Alias="pd" />
</References>
<Results>
<Property Source="pd" Name="alternate_id_seq" />
</Results>
<Ordering>
<Order Direction="Descending" Source="pd" Name="alternate_id_seq" />
</Ordering>
</Query>
<WhereCondition>[pd].[alternate_id] Like [prefix] & "*"</WhereCondition>
</Data>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">next_seq</Argument>
<Argument Name="Value">[pd].[alternate_id_seq]+1</Argument>
</Action>
</Statements>
</LookUpRecord>
<Action Name="SetField">
<Argument Name="Field">alternate_id_seq</Argument>
<Argument Name="Value">[next_seq]</Argument>
</Action>
<Action Name="SetField">
<Argument Name="Field">alternate_id</Argument>
<Argument Name="Value">[prefix] & [next_seq]</Argument>
</Action>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</DataMacro>
</DataMacros>
Now when new rows are added to the table the [alternate_id_seq] and [alternate_id] columns will be populated automatically.

Magento add limit to product collection

I'm trying to show last 150 added products.
I'm creating the module and add in xml
<reference name="content">
<!-- Add product list to content -->
<block type="newprod/product_list" name="product_list" template="catalog/product/list.phtml">
<!-- Add toolbar to product list -->
<block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
<!-- Add pager to toolbar -->
<block type="page/html_pager" name="product_list_toolbar_pager"/>
</block>
<!-- Specify toolbar block name -->
<action method="setToolbarBlockName">
<name>product_list_toolbar</name>
</action>
<!-- Use custom product collection -->
<action method="setCollection">
<value helper="newprod/getProductCollection" />
</action>
<!-- Use custom available sort by orders -->
<action method="setAvailableOrders">
<value helper="newprod/getAvailableOrders" />
</action>
<!-- Set the default sort by order -->
<action method="setSortBy">
<value>price</value>
</action>
<!-- Set default direction to ascending -->
<action method="setDefaultDirection">
<value>asc</value>
</action>
<action method="setColumnCount">
<column>12</column>
</action>
<action method="setLimit"><limit>50</limit></action>
</block>
</reference>
in getProductCollection
public function getProductCollection()
{
$collection = Mage::getResourceModel('reports/product_collection')
->addStoreFilter($store_id)
->addAttributeToFilter('visibility', 4)
->addAttributeToFilter('status', 1)
->addAttributeToSelect('*')
->setVisibility(array(2,3,4))
->setOrder('created_at', 'desc')
->setPage(1, 9);
return $collection;
}
but in result page I get n items on page and it's fine, but pager render for all 10000 products, how can I limit this? I'm trying to play with _beforeToHtml() function from mycomp_NewProd_Block_Product_List extends Mage_Catalog_Block_Product_List but now luck.
Maybe you can add
->setPageSize(150)
before return collection.

Create sequential ID value based on the year that a record is added

I am working on an Access 2013 database that will have different utility poles entered into the database and linked with other attributes. Each pole will have a unique global ID, and to simplify working I would like to add another unique ID that is more simple. I would like this field auto populated when a new pole in imported into the database. The ID would go as follows:
SAC(year)-(Escalating number, cannot be a duplicate)
ex. SAC16-20 (This would be the 20th pole entered into the database in 2016)
ex. SAC15-2536 (Would be the 2536th pole entered in 2015)
If anyone could help me generate some code to make this auto populate ID field work I would greatly appreciate it.
With Access versions 2010 and later you can use an event-driven data macro to generate the sequential ID. For example, say you have a table named [poledata]. Open it in Design View and add two fields:
alternate_id_seq – Numeric (Long Integer)
alternate_id – Text(20)
Save the changes to your table and then switch to Datasheet View.
In the Access ribbon, switch to the "Table Tools > Table" tab and click "Before Change"
then enter the following macro ...
... or paste the following XML into the macro editor window
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="BeforeChange">
<Statements>
<ConditionalBlock>
<If>
<Condition>[IsInsert]</Condition>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">next_seq</Argument>
<Argument Name="Value">1</Argument>
</Action>
<Action Name="SetLocalVar">
<Argument Name="Name">prefix</Argument>
<Argument Name="Value">"SAC" & Year(Date()) Mod 100 & "-"</Argument>
</Action>
<LookUpRecord>
<Data Alias="pd">
<Query>
<References>
<Reference Source="poledata" Alias="pd" />
</References>
<Results>
<Property Source="pd" Name="alternate_id_seq" />
</Results>
<Ordering>
<Order Direction="Descending" Source="pd" Name="alternate_id_seq" />
</Ordering>
</Query>
<WhereCondition>[pd].[alternate_id] Like [prefix] & "*"</WhereCondition>
</Data>
<Statements>
<Action Name="SetLocalVar">
<Argument Name="Name">next_seq</Argument>
<Argument Name="Value">[pd].[alternate_id_seq]+1</Argument>
</Action>
</Statements>
</LookUpRecord>
<Action Name="SetField">
<Argument Name="Field">alternate_id_seq</Argument>
<Argument Name="Value">[next_seq]</Argument>
</Action>
<Action Name="SetField">
<Argument Name="Field">alternate_id</Argument>
<Argument Name="Value">[prefix] & [next_seq]</Argument>
</Action>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</DataMacro>
</DataMacros>
Now when new rows are added to the table the [alternate_id_seq] and [alternate_id] columns will be populated automatically.

Create a concatenated list of child table values from an Access database without using VBA

I have an Access 2010 database with a relationship between parent and child tables. I would like to be able to query the database from an external application and show values from the child table as a concatenated list of values in a single column, similar to what MySQL can produce with its GROUP_CONCAT() function.
This has been asked here many times before, e.g., here:
Combine values from related rows into a single concatenated string value
but those solutions rely on a custom VBA function that is not available to external queries.
Is there a way to make such a concatenated list available to external queries without having to manually build the list in the other application?
Issue
Historically, the Access solution for a GROUP_CONCAT()-type query has been to use a VBA function like Allen Browne's ConcatRelated() (ref: here). However, custom VBA functions are only available to queries run from within Microsoft Access itself, so this is not a viable solution for queries against an Access database from some other application (e.g., a .NET application using OLEDB or ODBC).
Solution
With an Access 2010 (or newer) database we can emulate the behaviour of a MySQL GROUP_CONCAT() query by adding a Long Text ("Memo") field to the parent table and using data macros on the child table to maintain the concatenated list.
For example, for tables [Parents] ...
ParentID ParentName
-------- -------------
1 Homer Simpson
2 Ned Flanders
... and [Children] ...
ChildID ParentID ChildName DisplayOrder
------- -------- ----------------- ------------
1 1 Lisa 2
2 1 Bart 1
3 2 Rod, the elder 1
4 1 Maggie 3
5 2 Todd, the younger 2
... we can add a new Memo/Long Text field named [ChildList] to the [Parents] table and then add the following data macros to the [Children] table:
[Named Macro: UpdateChildList]
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Name="UpdateChildList">
<Parameters>
<Parameter Name="prmParentID"/>
</Parameters>
<Statements>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">newList</Argument>
<Argument Name="Value">Null</Argument>
</Action>
<ForEachRecord>
<Data Alias="c">
<Query>
<References>
<Reference Source="Children" Alias="c"/>
</References>
<Results>
<Property Source="c" Name="ChildName"/>
</Results>
<Ordering>
<Order Source="c" Name="DisplayOrder"/>
</Ordering>
</Query>
<WhereCondition>[c].[ParentID]=[prmParentID] And [c].[ChildName] Is Not Null</WhereCondition>
</Data>
<Statements>
<ConditionalBlock>
<If>
<Condition>Not IsNull([newList])</Condition>
<Statements>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">newList</Argument>
<Argument Name="Value">[newList] & ";" & Chr(160)</Argument>
</Action>
</Statements>
</If>
</ConditionalBlock>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">newList</Argument>
<Argument Name="Value">[newList] & [c].[ChildName]</Argument>
</Action>
</Statements>
</ForEachRecord>
<LookUpRecord>
<Data>
<Reference>Parents</Reference>
<WhereCondition>[Parents].[ParentID]=[prmParentID]</WhereCondition>
</Data>
<Statements>
<EditRecord>
<Data/>
<Statements>
<Action Collapsed="true" Name="SetField">
<Argument Name="Field">Parents.ChildList</Argument>
<Argument Name="Value">[newList]</Argument>
</Action>
</Statements>
</EditRecord>
</Statements>
</LookUpRecord>
</Statements>
</DataMacro>
</DataMacros>
[After Insert]
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="AfterInsert">
<Statements>
<Action Name="RunDataMacro">
<Argument Name="MacroName">Children.UpdateChildList</Argument>
<Parameters>
<Parameter Name="prmParentID" Value="[ParentID]"/>
</Parameters>
</Action>
</Statements>
</DataMacro>
</DataMacros>
[After Update]
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="AfterUpdate">
<Statements>
<ConditionalBlock>
<If>
<Condition>Updated("ParentID") Or Updated("ChildName")</Condition>
<Statements>
<Action Name="RunDataMacro">
<Argument Name="MacroName">Children.UpdateChildList</Argument>
<Parameters>
<Parameter Name="prmParentID" Value="[ParentID]"/>
</Parameters>
</Action>
<ConditionalBlock>
<If>
<Condition>Updated("ParentID")</Condition>
<Statements>
<Action Name="RunDataMacro">
<Argument Name="MacroName">Children.UpdateChildList</Argument>
<Parameters>
<Parameter Name="prmParentID" Value="[Old].[ParentID]"/>
</Parameters>
</Action>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</DataMacro>
</DataMacros>
[After Delete]
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="AfterDelete">
<Statements>
<Action Name="RunDataMacro">
<Argument Name="MacroName">Children.UpdateChildList</Argument>
<Parameters>
<Parameter Name="prmParentID" Value="[Old].[ParentID]"/>
</Parameters>
</Action>
</Statements>
</DataMacro>
</DataMacros>
Results
As changes are made to the child table the list in the parent table will automatically be updated:
ParentID ParentName ChildList
-------- ------------- ---------------------------------
1 Homer Simpson Bart; Lisa; Maggie
2 Ned Flanders Rod, the elder; Todd, the younger
Notes
The [ChildList] field is for display purposes only. Editing the values in that field will not change the values in the child table.
The list is separated with ";" & Chr(160) to differentiate it from any ";" & Chr(32) pairs that may be in the actual data. If the non-breaking space (Chr(160)) characters mess up wrapping of the list then we could use the Replace() function in our query to convert ";" & Chr(160) to ";" & Chr(32) or "," & Chr(32) or whatever would be most appropriate.
To populate the lists with existing child data we simply need to "update" one child record for each parent, like so
UPDATE Children SET ChildName=ChildName
WHERE ChildID IN (SELECT MIN(ChildID) AS m FROM Children GROUP BY ParentID)