I have written a workflow for that autofills a column in a sharepoint list. When I add a new entry nothing happens. However, if I go to another list and then return to the list with the workflow I can see that it has worked. I have set up the workflow to start when a new item is created, is there some other setting in the workflow to make it update instantly?
No there is no. You should use SPItemEventReceiver instead and use ItemUpdating method. This is what works instantly and the workflow requires some time to start and it runs asynchronously. Furthermore workflows are heavy and you should avoid using them for very simple actions.
The sample code for an event receiver is
public class MyEventReceiver :SPItemEventReceiver
{
public override void ItemUpdating(SPItemEventProperties properties)
{
UpdateField(properties);
}
public override void ItemAdding(SPItemEventProperties properties)
{
UpdateField(properties);
}
private void UpdateField(SPItemEventProperties properties)
{
EventFiringEnabled = false;
var item = properties.ListItem;
// do calculation here
item.SystemUpdate(false); // this update that is most suitable for automatic updates
EventFiringEnabled = true;
}
}
And then add this event receiver to a list. I hope this link helps
You can also try to add a Calculated column to your list if you cannot use Visual Studio. This way the hardest point is to define a formula that will takes data from other columns of the list item and performs a calculation. link1 and link2 can give you more information on how to write a formula in the calculated column in SharePoint with no code.
Related
I need to add a filter to the Process Orders screen grid, so that only orders that have an unpaid balance = 0 will show, based on an additional checkbox to the filter area called 'Must Have Payment' being checked. I thought I had it by adding a where clause to the Orders view, but that didn't work.
[PXFilterable]
public PXFilteredProcessing<SOOrder, SOOrderFilter,
Where<SOOrder.unpaidBalance, NotEqual<Zero>,
Or<Current<SOOrderFilterExt.mustHavePayment>, Equal<False>>>> Orders;
I'm sure I'm doing this incorrectly, as all orders are showing and not just the 'Open' orders as it was before I added this change. I'd like to override the view delegate and modify that to add my filter / condition to the returned rows, but I can't override this method - at least that I can tell.
What's the best way to get this custom filter restriction into the select for that grid?
Thanks much...
Overriding the dataview delegate may not be the best idea on this specific case.
I noticed that AddCommonFilters() method is not private (used in the dataview delegate), so I think you could try to override this method instead, call Base method and then inject your custom code to include your query filter into the main query used on the for each.
Maybe this is something you can use to implement your filtering, see snippet below:
public class SOCreateShipment_Extension : PXGraphExtension<SOCreateShipment>
{
#region Event Handlers
public delegate void AddCommonFiltersDelegate(SOOrderFilter filter,
PXSelectBase<SOOrder> cmd);
[PXOverride]
public void AddCommonFilters(SOOrderFilter filter, PXSelectBase<SOOrder> cmd, AddCommonFiltersDelegate baseMethod)
{
baseMethod(filter,cmd);
//Add your custom code here
if (Yourcondition)
{
cmd.WhereAnd<Where<YOURFILTERINGCondition>>>>();
}
}
........................
Please also review the AlterFilters() method if needed.
We're using the Run Project Billing screen to create records in AR / Invoice and Memo.
In the Invoice & Memo screen, we need the process to populate the header Customer Ord. number, along with a user field that has been added to the grid section on the 'Document Details' tab. At the moment, the process is not doing this.
I'd like to intercept the processing action on the screen using a technique I'm familiar with, namely using an 'AddHandler':
[PXOverride]
protected virtual IEnumerable Items (PXAdapter adapter)
{
PXGraph.InstanceCreated.AddHandler<BillingProcess>((graph) =>
{
graph.RowInserting.AddHandler<BillingProcess.ProjectsList>((sender, e) =>
{
//Custom logic goes here
});
});
return Base.action.Press(adapter);
}
I see no Base.Actions that remotely resembles 'Bill' or 'Bill All'.
This is obviously not exactly the code I need, but I would think this is the general place to start.
After reviewing the source business logic, I don't see any 'Bill' or 'Bill All' Actions - or any 'Actions' at all (baffling). I see an IEnumerable method called 'items', so that's what I started with above.
Is this the correct way to go about this?
Update: 2/14/2017
Using the answer provided re: the overridden method InsertTransaction(...) I've tried to set our ARTran user field (which is required) using the following logic:
PMProject pmproj = PXSelect<PMProject, Where<PMProject.contractID, Equal<Required<PMProject.contractID>>>>.Select(Base, tran.ProjectID);
if (pmproj == null) return;
PMProjectExt pmprojext = PXCache<PMProject>.GetExtension<PMProjectExt>(pmproj);
if (pmprojext == null) return;
ARTranExt tranext = PXCache<ARTran>.GetExtension<ARTranExt>(tran);
if (tranext == null) return;
tranext.UsrContractID = pmprojext.UsrContractID;
Even though this sets the user field to the correct value, it still gives me an error that the required field is empty when the process finishes. My limited knowledge prevents me from understanding why.
On the Run Project Billing screen, captions of Process and Process All buttons were changed to Bill and Bill All respectively in BLC constructor.
Process delegate is set for Items data view within the BillingFilter_RowSelected handler:
public class BillingProcess : PXGraph<BillingProcess>
{
...
public BillingProcess()
{
Items.SetProcessCaption(PM.Messages.ProcBill);
Items.SetProcessAllCaption(PM.Messages.ProcBillAll);
}
...
protected virtual void BillingFilter_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
BillingFilter filter = Filter.Current;
Items.SetProcessDelegate<PMBillEngine>(
delegate (PMBillEngine engine, ProjectsList item)
{
if (!engine.Bill(item.ProjectID, filter.InvoiceDate, filter.InvFinPeriodID))
{
throw new PXSetPropertyException(Warnings.NothingToBill, PXErrorLevel.RowWarning);
}
});
}
...
}
As code snippet above confirms, all records in the AR Invoice and Memos screen are created by instance of the PMBillEngine class. Below is code snippet showing how to override InsertNewInvoiceDocument and InsertTransaction methods within the PMBillEngine BLC extension:
public class PMBillEngineExt : PXGraphExtension<PMBillEngine>
{
public delegate ARInvoice InsertNewInvoiceDocumentDel(string finPeriod, string docType, Customer customer,
PMProject project, DateTime billingDate, string docDesc);
[PXOverride]
public ARInvoice InsertNewInvoiceDocument(string finPeriod, string docType, Customer customer, PMProject project,
DateTime billingDate, string docDesc, InsertNewInvoiceDocumentDel del)
{
var result = del(finPeriod, docType, customer, project, billingDate, docDesc);
// custom logic goes here
return result;
}
[PXOverride]
public void InsertTransaction(ARTran tran, string subCD, string note, Guid[] files)
{
// the system will automatically invoke base method prior to the customized one
// custom logic goes here
}
}
Run Project Billing process invokes InsertNewInvoiceDocument method to create new record on the AR Invoice and Memos screen and InsertTransaction method to add new invoice transaction.
One important thing to mention: overridden InsertNewInvoiceDocument and InsertTransaction methods will be invoked when a user launches Run Project Billing operation either from the processing Run Project Billing screen or from the data entry Projects screen.
For more information on how to override virtual BLC methods, see Help -> Customization -> Customizing Business Logic -> Graph -> To Override a Virtual Method available in every Acumatica ERP 6.1 website
there is a problem!!
In javafx table view i applied multiple selected mode by Shift+mouseClick or Clt+MouseClick. By This
tblViewCurrentStore.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
tblViewCurrentStore.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
}
});
it's ok on GUI but problem is, if i use this code it give me the last selection cell's value,
private void btnDeleteOnAction(ActionEvent event) {
System.out.println(tblViewCurrentStore.getSelectionModel().getSelectedItem().getProductName().toString());
}
Out Put SAMSUNG HDD
but when i use this code it give this!
private void btnDeleteOnAction(ActionEvent event) {
System.out.println(tblViewCurrentStore.getSelectionModel().getSelectedItems().toString());
}
It Give me This types of output
[List.ListProduct#3a22ea22, List.ListProduct#6d99efa2, List.ListProduct#40fd0f67]
But i need when i select multiple row then press delete it will show all selected data like first one.
Hear is my GUI(With multiple selection)
You can even use this :
ArrayList<YourModel> products = new ArrayList<>(table.getSelectionModel().getSelectedItems());
for (YourModel model : models) {
System.out.println(model);
}
//OR
final List<YourModel> collect = table.getSelectionModel().getSelectedItems().stream().collect(Collectors.toList());
There are multiple problems with your code:
tblViewCurrentStore.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);only needs to be set once (thus its a setter). Do it after your TableView has been initialized and not on every click.
SelectionModel#getSelectedItem() clearly says what it does:
Returns the currently selected object (which resides in the selected index position). If there are multiple items selected, this will return the object contained at the index returned by getSelectedIndex() (which is always the index to the most recently selected item).
And finally SelectionModel#getSelectedItems returns all selected objects (as in Java Objects).
So if you want the names, you can something like this:
List<String> names = tblViewCurrentStore.getSelectionModel().getSelectedItems().stream()
.map(ListProduct::getProductName)
.collect(Collectors.toList());
on ItemAdded on a field,
public override void ItemAdded(SPItemEventProperties properties)
{
this.EventFiringEnabled = false;
using (SPWeb web = new SPSite(properties.WebUrl).OpenWeb())
{
SPList list = web.Lists[properties.ListId];
SPListItem item = list.GetItemById(properties.ListItemId);
var test = item["MyField"] = "";
item.SystemUpdate(false);
}
this.EventFiringEnabled = true;
}
}
}
when adding a dokument directly to my library its clear the field, men when i publish the document and then try to unpublish and then i select Remove this document but create a draft of the document, on this event it wont clear my field, i get the value and everything but in the en it still has the old value?
I've not checked this for sure but I think I remember when dealing with event receivers in document libraries it's a little funny. I believe the itemAdded event fires when you upload the document, you then continue to fill out your metadata for that document and when you click save the itemupdating and itemupdated event is fired. If you debug you will see this I think.
I believe you want to change to ItemUpdated
Cheers
Truez
I've got the following problem:
I created a WebPart with a ToolPart,
this toolpart has multiple controls (textbox, dropdownlist, ...)
when I fill in everything and apply, it all goes ok,
even when i press ok. But when i go back to
edit -> modify webpart, all my data i've entered is gone.
How can i solve this?
Thanks
You'll need to save the values from the Toolpart in the webpart's properties. For example, lets say I want to save a string for "Title"... in the webpart define a property:
private const string DEFAULT_WPPColumnTitle = "Title";
private string _WPPColumnTitle = DEFAULT_WPPColumnTitle;
[Browsable(false)]
[WebPartStorage(Storage.Shared)]
public string WPPColumnTitle
{
get { return this._WPPColumnTitle; }
set { this._WPPColumnTitle = value; }
}
I always use the prefix "WPP" to keep all the web part properties together.
Then, in the Toolpart's ApplyChanges override, save the control's value (_ddlColumnsTitle) to the webpart (WPPColumnTitle):
/// <summary>
/// Called by the tool pane to apply property changes to
/// the selected Web Part.
/// </summary>
public override void ApplyChanges()
{
// get our webpart and set it's properties
MyCustomWebPart et = (MyCustomWebPart)ParentToolPane.SelectedWebPart;
et.WPPColumnTitle = _ddlColumnsTitle.SelectedValue;
}
Lastly, if the user edited the properties already, we want the Toolpart to be pre-populated with the user's configuration. In the CreateChildControls() method of your Toolpart, initialize the controls:
protected override void CreateChildControls()
{
try
{
MyCustomWebPart et = (MyCustomWebPart)ParentToolPane.SelectedWebPart;
// ... code to create _ddlColumnsTitle and add it to the Controls
// default our dropdown to the user's selection
ListItem currentItem = _ddlColumnsTitle.Items.FindByValue(et.WPPColumnTitle);
if (null != currentItem)
{
_ddlColumnsTitle.SelectedValue = currentItem.Value;
}
}
catch (Exception ex)
{
_errorMessage = "Error adding edit controls. " + ex.ToString();
}
}
Open up the debugger and double check that the values are getting applied to your propertries on Apply (i.e. WPPColumnTitle is set).
If so then problem is that SharePoint is not serializing/deserializing the value from the property (WPPColumnTitle) to the database and back - verify by writing out this property on the web part - as soon as you leave the page and come back it will be empty.
If so then check things like this on class
[XmlRoot(Namespace = "YourNamespace")]
and this (not strictly necessary) on properties
[XmlElement(ElementName = "ColumnTitle")]
I've also seen problems if you name your web part class "WebPart" so call it MyWebPart
I've solved it with adding a property in my webpart "IsNeverSet" (bool)
and when i go to the "CreateControls()" of my toolpart, I get this property
and if it's false, I load all the properties from my webpart and fill them in the toolpart.
So I found it with the help of Kit Menke