DBGrid - OnCellClick & OnDblClick, return a form/TBMemo containing cell/column value/s - mysql

I'm using the following code added to my DBGrid - OnCellClick event
procedure TForm2.DBGrid1CellClick(Column: TColumn);
begin
if dbmodule.comenziDataSet.Active then
begin
if not Assigned(dbgridCelulaForm) then
begin
dbgridCelulaForm := TdbgridCelulaForm.Create(Self);
dbgridCelulaForm.DBMemoCelula.DataSource := dbmodule.comenziSource;
end;
dbgridCelulaForm.Visible := False;
dbgridCelulaForm.Visible := True;
dbgridCelulaForm.DBMemoCelula.DataField := Column.FieldName;
dbgridCelulaForm.Caption := Format('%s / randul: %d',[Column.FieldName, DBGrid1.DataSource.DataSet.RecNo]);
end;
end;
dbgridCelulaForm = name of the form containing the TDBMemo
DBMemoCelula = name of the TDBMemo
dbmodule.comenziDataSet = comenziDataSet is the name of the DataSet and dbmodule is the name of a data module (unit, like forms) - the DataSet is on the data module, so, dbmodule.comenziDataSet
dbmodule.comenziSource = same as data set, a DataSource on a data module, the source is named comenziSource
Ok so what this code does:
Once I click a cell on my DBGrid it pops up a form (named dbgridCelulaForm) which contains a TBMemo (named DBMemoCelula) and it shows me the information contained in that cell (like, a Customer Name for example, or whatever the cell is holding, in my db)
This is fine, my problem is I can't select rows now in DBGrid, well, I can but once I do the 1st place I click (a cell, any) on the particular row I want to select with my mouse, then cell activates and the form pops up.
Is it possible to use this code in DBGrid - OnDblClick event instead of the OnCellClick ?
Meaning once i double click a row / cell the form should pop up and show me the info, but double click - not single click.
That way, I can still select the row and still view the info in the cell if I need to.
Or any other way/place to use/receive this functionality.
Any thoughts?
I can post a quick video of everything if my explanation is ambiguous and you think that would help, just tell me in the comment / answer.
Also, I'm using RAD Studio 10 Seattle and dbexpress components for the database - if that helps.
Thanks!

The following code shows how to access the Column and Row coordinates of a dbl-clicked cell of a TDBGrid, and the string value of the cell contents.
As written, it displays the cell's Column and Row number + string contents on the form's caption. Up to you what you actually do with these values.
It work because the dataset cursor on the dataset connected to the DBGrid is moved to the dataset row corresponding to the cell where the mouse pointer is.
type
TMyDBGrid = class(TDBGrid);
procedure TForm1.DBGrid1DblClick(Sender: TObject);
var
ARow,
ACol : Integer;
Pt : TPoint;
CellValue : String;
begin
// First, get the mouse pointer coordinates
Pt.X := Mouse.CursorPos.X;
Pt.Y := Mouse.CursorPos.Y;
// Translate them into the coordinate system of the DBGrid
Pt := DBGrid1.ScreenToClient(Pt);
// Use TDBGrids inbuilt functionality to identify the Column and
// row number.
ACol := DBGrid1.MouseCoord(Pt.X, Pt.Y).X -1;
ARow := DBGrid1.MouseCoord(Pt.X, Pt.Y).Y;
CellValue := DBGrid1.Columns[ACol].Field.AsString;
Caption := Format('Col:%d Row:%d Cell Value:%s', [ACol, ARow, CellValue]);
end;
Note that I've used the Caption property of the form to display the grid cell info just as a quick n dirty way of showing the information somewhere. Of course you could equally well display it on another area of the form or somewhere on a different form entirely. The above code will work equally well in the grid's OnCellClick event, btw.
As noted in a comment, you can use the grid's SelectedField property instead of the above, but personally I think the above is more instructive of how to work with a DBGrid, because it shows how to get the cell's Column and Row coordinates. See the DBGrid's SelectedField, SelectedIndex and SelectedRows properties in the Online Help for more info on useful properties of the TDBGrid.
Update You asked in a comment for an example of showing the information on another form. Let's suppose this form is called OtherForm, is in a unit OtherFormu.Pas and is created before the DBGrid1DblClick evenbt is called. You need to use this unit in the Useslist of the unit which contains the DBGrid. Let's suppose this other form contains a TMemo control called Memo1. Then, you could write your DBGrid1DblClick hanndler like this:
procedure TForm1.DBGrid1DblClick(Sender: TObject);
[as above]
begin
[ as above ]
CellValue := DBGrid1.Columns[ACol].Field.AsString;
OtherForm.Memo1.Lines.Add(Format('Col:%d Row:%d Cell Value:%s', [ACol, ARow, CellValue]));
end;

Related

Passing inherited frames as argument to a procedure

I have a TPageControl with N amount of TTabSheets in my main form which I use to embed several TFrame descendants.
For the frames I created a "TBaseFrame" from which I derive the individual frames which I want to display in the TabSheets, more or less looks like this...
TBaseFrame = class(TFrame)
TBaseFrameDescendant1 = class(TBaseFrame)
TBaseFrameDescendant2 = class(TBaseFrame)
TBaseFrameDescendantN = class(TBaseFrame)
What im struggleing with is this: I want to create a procedure that takes any of my TBaseFrameDescendants as an argument, creates the given frame and displays it in a new tab sheet. I started with something like this...
procedure CreateNewTabSheetAndFrame( What do I put here to accept any of my TBaseFrameDescendants? )
var
TabSheet: TTabSheet;
begin
TabSheet := TTabSheet.Create(MainPageControl);
TabSheet.Caption := 'abc';
TabSheet.PageControl := MainPageControl;
// Here I want to create the given TBaseFrameDescendant, set the Parent to the above TabSheet and so on
end;
Guess my main question here is how to set up my procedure so I can pass in any frame which is derived from my TBaseFrame so I can work with it within the procedure, or am I heading in the wrong direction here?
You need to use what is known as a metaclass.
type
TBaseFrameClass = class of TBaseFrame;
procedure TMainForm.CreateNewTabSheetAndFrame(FrameClass: TBaseFrameClass)
var
TabSheet: TTabSheet;
Frame: TBaseFrame;
begin
TabSheet := TTabSheet.Create(Self);
TabSheet.PageControl := MainPageControl;
Frame := FrameClass.Create(Self);
Frame.Parent := TabSheet;
end;
Make sure that if you declare any constructors in any of your frame classes, that they derive from the virtual constructor introduced in TComponent. That is necessary in order for the instantiation via metaclass to invoke the appropriate derived constructor.

Value Calculation issue in Google web HTML App

I have created an HTML web app in google script this works like a calculator, This app works fine if I add the input in descending order however if I skip the order and update in put data numbers randomly in any column then I am not getting the output properly
Example:- update the numbers in box number 4 and 5 then update in box number 1 you will find the differences in total numbers
Please refer the attached sheet for detailed script
Project Name- Project Proposal Form
$("#rTpe1").keyup(function(e){
$("#rFor1").val(this.value * $("#PerHourRate1").val());
$("#rFor3").val( Number($("#rFor1").val()) +Number($("#rFor2").val()))
});
$("#rTpe2").keyup(function(e){
$("#rFor2").val(this.value * $("#PerHourRate2").val());
$("#rFor3").val( Number($("#rFor1").val()) + Number($("#rFor2").val()))
});
$("#rTpe12").keyup(function(e){
$("#rFor12").val(this.value * $("#PerHourRate3").val());
$("#rFor3").val( Number($("#rFor1").val()) + Number($("#rFor2").val())+ Number($("#rFor12").val()))
});
$("#rTpe13").keyup(function(e){
$("#rFor13").val(this.value * $("#PerHourRate4").val());
$("#rFor3").val( Number($("#rFor1").val()) + Number($("#rFor2").val())+ Number($("#rFor12").val())+ Number($("#rFor13").val()))
});
I could be wrong, but I think that's the main culprit:
If your work your way top to bottom, the output in '#rFor3' is not affected. For example, if you enter values in the first field ('#rTpe1'), this statement
Number($("#rFor2").val()))
will evaluate to '0' because '#rFor2' probably contains an empty string at this point and Number("") will get you a zero. Because all subsequent input fields reference the results of previous calculations ('rTpe2' references 'rFor1', 'rTpe12' references both 'rFor1' and 'rFor2', etc), the sum will come out as correct.
Now consider the reverse scenario. For simplicity, let's make all your rates equal to 1. If you enter the value of '5' into 'rTpe12', the value of 'rFor3' will be
Number("") + Number("") + Number(5*1) == 5; //the first two inputs will contain empty strings at this point
The output of '#rFor3' would be 5. If you go up a step and enter the value of '2' into 'rTpe2', the value of the 'rFor3' output will change to
Number("") + Number(2*1) == 2; the first input will contain an empty string.
The code is not easy to understand, so even if this solution doesn't work for you, consider caching your DOM elements to improve performance and make your code more readable. Currently, you are using jQuery selectors to search the DOM over and over again, which is a serious performance drag. You could also store your calculated value as a variable and simply add values to it instead of recalculating on each input. For example
$('document').ready(function(){
var total = 0;
var input1 = $('#input1');
var input2 = $('#input1');
var input3 = $('#input1');
var output = $('#output');
input1.keyup(function(e){
var value = Number(this.value);
sum += value;
output.val(sum);
});
});

How to map a document list in WEBMethods?

I want to map an array which in WebMethods is a document list. I thought that you could just map that variable over without mapping all of the children. I have done this and nothing shows in the PassArea. (PassArea is the data array that is being sent to a mainframe program afterwards.)
A --> B
Field1 F1
Field2 F2
field3 F3
The document is A and the input document into the Natural program is B. The --> is the link that connects them together.
I don't have an image to show, because that would reveal some company information.
If the fields of document list "A" has different names than the fields of document list "B" then no, you cannot map document list "A" to document list "B". WebMethods doesn't know which field from A corresponds to what field from "B".
You will have to do the following:
LOOP over document list "A"
Map each field of "A" to a generic document containing the same fields as document list "B"
Append the generic document to document list "B"
Drop the generic
document.
Step #2 screenshot
Step #3 screenshot
There's a lot ways to map between arrays of documents. But before you create one, consider these writings:
Techcommunity SoftwareAG - performance impact with appendToDocumentList
quest4apps.com - Reason to avoid appendToDocumentList
As hint from #2 said that there's 6 ways they ranked as follows from fastest to slowest (but I'm going to give an example in first three, because the latter three is quite obviously slow, which considered to be avoided):
1. Java Loop: looping done through a Java service.
The easiest way to create java service is to map the input output first.
Right-click and click on "Generate Code" until the dialog box appears
Choose the option "For implementing this service"
And the service is created
Just re-arrange the code into this:
public static final void mappingDocuments(IData pipeline) throws ServiceException {
// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
// Instantiate input A
IData[] A = IDataUtil.getIDataArray(pipelineCursor, "A");
// Initiate output B
IData[] B = new IData[A.length];
if (A != null)
{
for (int i = 0; i < A.length; i++)
{
// Populate the Field in doc A
IDataCursor ACursor = A[i].getCursor();
String Field1 = IDataUtil.getString(ACursor, "Field1");
String Field2 = IDataUtil.getString(ACursor, "Field2");
String Field3 = IDataUtil.getString(ACursor, "Field3");
ACursor.destroy();
// Create IData[i] and cursors finally put all Fields into B[i] variable output
B[i] = IDataFactory.create();
IDataCursor BCursor = B[i].getCursor();
IDataUtil.put(BCursor, "F1", Field1);
IDataUtil.put(BCursor, "F2", Field2);
IDataUtil.put(BCursor, "F3", Field3);
BCursor.destroy();
// OR JUST USE CLONE BELOW IF YOU DON'T HAVE ANY MODIFICATION INSIDE THE VARIABLE
// B[i] = IDataUtil.clone(A[i]);
}
}
pipelineCursor.destroy();
// Finally to put the B Map(IData) to output.
// Actually you can use only single pipelineCursor throughout all code but it's just for readable
IDataUtil.put(pipelineCursor, "B", B);
pipelineCursor.destroy();
}
Result
2. Implicit Loop: for simple lists of the same size, you may want to link them directly in a MAP step
Create flow service and input & output document
Create MAP step
Select both document in ForEach loop.
3. Explicit Loop: using a LOOP step and its Output Array.
Create flow service and input & output document
Create LOOP step
Change the properties of LOOP, input array=A; output array=B; and create a map under LOOP step
Map all parameters in A to B
Hope these helps...

Scilab - calling another GUI within a GUI. Functions not working

I'm quite new to scilab, I have created two GUIs (see example below), with script 2 being called from script 1. However the function in script 2 don't seem to work. Can anyone help?
Script 1
'//////////
f=figure('figure_position',[0,0],'figure_size',[1250,650]);
//////////
delmenu(f.figure_id,gettext('File'))
delmenu(f.figure_id,gettext('?'))
delmenu(f.figure_id,gettext('Tools'))
toolbar(f.figure_id,'off')
handles.dummy = 0 ;
handles.exam=uicontrol(f,'unit','normalized','BackgroundColor', [0.5,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.5,0.5,0.1,0.05],'Relief','flat','SliderStep',[0.01,0.1],'String','exam','Style','pushbutton','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','obj102','Callback','exam_callback(handles)')
function exam_callback(handles)
close(f);
clear
exec('costs0-1.sce',-1) ;
endfunction`
Script 2
////////// Defining the figure (size, name etc)/////////////////////////////
f=figure('figure_position',[0,0],'figure_size',[1250,650],'auto_resize','on','background',[8]);
//////////
delmenu(f.figure_id,gettext('File'))
delmenu(f.figure_id,gettext('?'))
delmenu(f.figure_id,gettext('Tools'))
toolbar(f.figure_id,'off')
//Cabinet - TEXT
handles.obj17=uicontrol(f,'unit','normalized','BackgroundColor',[1,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[12],'FontUnits','points','FontWeight','normal','ForegroundColor',[0,0,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.15,0.93,0.1,0.05],'Relief','flat','SliderStep',[0.01,0.1],'String','Cabinet','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','obj17','Callback','')
// Cabinet - POP UP MENU
handles.service=uicontrol(f,'unit','normalized','BackgroundColor',[0.8,0.8,0.8],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[12],'FontUnits','points','FontWeight','normal','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.25,0.93,0.15,0.05],'Relief','flat','SliderStep',[0.01,0.1],'String','1|2','Style','popupmenu','Value',[1],'VerticalAlignment','middle','Visible','on','Tag','service','Callback','service_callback(handles)')
// CALCULATE PUSHBUTTON
handles.Calculate=uicontrol(f,'unit','normalized','BackgroundColor',[0,0.8,0],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[16],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.22,0.02,0.15,0.08],'Relief','raised','SliderStep',[0.01,0.1],'String','CALCULATE','Style','pushbutton','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','Calculate','Callback','Calculate_callback(handles)')
// Resources- TEXT
handles.Resourcestxt=uicontrol(f,'unit','normalized','BackgroundColor',[1,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.75,0.95,0.20,0.05],'SliderStep',[0.01,0.1],'String','Resources in hours','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','','Callback','')
// TOTAL hours - TEXT
handles.totalhourstxt=uicontrol(f,'unit','normalized','BackgroundColor',[1,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.75,0.75,0.12,0.05],'SliderStep',[0.01,0.1],'String','Total Hours','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','','Callback','')
// hardware hours - text
handles.totalhours=uicontrol(f,'unit','normalized','BackgroundColor',[0.95,1,1],'Enable','on','FontAngle','normal','FontName','helvetica','FontSize',[14],'FontUnits','points','FontWeight','bold','ForegroundColor',[0,0.5,0],'HorizontalAlignment','center','ListboxTop',[],'Max',[1],'Min',[0],'Position',[0.88,0.75,0.08,0.05],'SliderStep',[0.01,0.1],'String','','Style','text','Value',[0],'VerticalAlignment','middle','Visible','on','Tag','totalhours','Callback','')
function Calculate_callback(handles)
if handles.service.value == 1 then
resource_hrs = 2
end
if handles.service.value == 2 then
resource_hrs = 10
end
set(handles.totalhours,'String',string(resource_hrs));
endfunction
Problem
It is a scoping problem. When function exam_callback() gets called it runs the other script with exec('costs0-1.sce',-1).
In that script you define the function Calculate_callback(handles). This goes out of scope and is deleted when exam_callback() is finished and as such can't be called when the button is pressed.
The second problem is that the handles are not globally affected, so when leaving exam_callback() the handles of the second Cost Gui are not added to handles.
Solution
You can move the generating of the GUI into a function createCostGui() and then load script2 at the start of script1 with exec('costs0-1.sce',-1);.
To make Calculate_callback(handles) function discard the handles argument and use the tags to find the handles
function Calculate_callback()
serviceHandle = findobj('tag','service');
if serviceHandle.value == 1 then
resource_hrs = 2
end
if serviceHandle.value == 2 then
resource_hrs = 10
end
totalHoursHandle = findobj('tag','totalhours');
set(totalHoursHandle,'String',string(resource_hrs));
endfunction
Further remarks
Text elements are generally static and thus don't need a Callback argument.
If you want an argument to stay at its default value, you don't need to specify them.
From the Scilab documentation:
h = uicontrol(PropertyName, PropertyValue,...) creates an uicontrol and assigns the specified properties and values to it. It assigns the default values to any properties you do not specify. The default uicontrol style is a "Pushbutton". The default parent is the current figure. See the Properties section for information about these and other properties.
Small remark on your question
Next time an error message could help with making your question more specific.

Creating a user generated list in flash

I'm trying to create a flash application that will keep track of user generated values. The app should basically allow the user to input the name of the item and it's cost. The total costs should then be added up to show a total value to the user. I can probably figure out how to add the values together, but I'm not really sure how to allow the user to create a list and then allow the user to save it. Can anyone point me towards a tutorial or point me in the right direction?
I am using variables to add user inputed numbers to come up with a total. The first problem is that actionscript 3.0 does not allow variables for texts. I just converted it to 2.0 to fix this. The second problem, is when I test the app and put in my values and click submit, I get NaN in the total values field. Is there a reason why it wouldn't add the values?
Here is the code I used for the submit button:
on (release) {
total = Number(rent) + Number(food) + Number(travel) + Number(entertainment) + Number(bills);
}
Am I missing anything?
Can I give the input text instance names and then give them variables? How are some ways to go about this?
Thanks for the help!
Have an object array, say for example
var stack:Array = new Array();
Then push the item name and it's cost to that array when user inputs, like
stack.push({item:AAA, cost:xx});
So that you can generate the list whenever you want with that array.
You have to see how this works in code. A list in actionscript could be stored inside an array, vector, dictionary or even an Object.
Var myList:Array = [];
myList.push({name: "item 1", cost: 5 });
myList.push({name: "item 2", cost: 7.5 });
If you want to grab the 'product' of "item 1" from the list, you have to create a function for that, lets call it getProductByName
function getProductByName(name:String):Object
{
for each(var product:Object in myList)
{
if (product.name === name) return product;
}
return null; // no match found
}
You can call that function like this:
var product = getProductByName("item 1");
trace(product.cost); // 5
And you can alter the product, so lets make it more expensive
product.cost += 1;
trace(product.cost); // 6
Have fun! If you are using classes, you would create one for the product, with public name and cost, and in that case you'de better use a vector, to ensure working with the right type.
This is what fixed the issue for me in action script 3.0:
myButton.addEventListener(MouseEvent.CLICK, addThem);
function addThem(e:MouseEvent)
{
totalField.text = String ( Number(field1.text) + Number(field2.text) + ....);
}
I also had to name the instances appropriately.