I need to find column (on each sheet excluding ProfitSheet) which first cell has specified value (it always exists and only one per sheet) and then copy column to another sheet. i.e. something like that:
for i := 2 to MsExcel.Sheets.Count do // sheets loop. Sheets[1] — ProfitSheet
begin
MsExcel.Sheets[i].Select;
for j := 1 to 15 do // columns loop to find "Profit column"
if MsExcel.Cells[1, j].Text = 'Profit' then
// copy j column, usually I use something like
// VariantArr := MsExcel.Range[MsExcel.Cells[1, j], MsExcel.Cells[299, j]].Value
// and then
// Range := MsExcel.Range[MsExcel.Cells[1,i], MsExcel.Cells[299, i]];
// Range.Value := VariantArr;
// but I don't know how to find last column's cell (where 299)
MsExcel.Sheets['ProfitSheet'].Select;
// copy col to the i column of ProfitSheet
end;
Related
I am trying to extract the Name of a person out of my database, containing two tables, with only having the ID (primary key).
I am struggling to come up with a solution, although I do have notes that I've written and the logic seems to check out (to me at least).
if P1Score > P2Score
then winner := P1ID
else winner := P2ID
winner in tblGames = the ID of winner in tblPlayers
WinnerName := first name of Winner + surname of Winner in tblPlayers
So this is my logic, obviously it's missing a lot, but I can't seem to expand on it much more
I have the ID of the person from tblGames, but now I'm struggling to understand how to use that ID to extract the Name and Surname from my tblPlayers and assign it to a variable, so I can put it into the Winner Column of tblGames.
I have tried a few things using my own thought process, but I do not know enough about Delphi and databases to actually implement it correctly.
BEGIN
if (StrToInt(P1_score) - StrToInt(P2_score) = 0) then
Draw := True
else
Draw:= False;
if StrtoInt(P1_Score) > StrToInt(P2_Score) then
winnerID := P1_ID
else
winnerID := P2_ID;
with dmTournament do
begin
tblGames.Insert;
tblGames['Player1_Id'] := StrToInt(P1_ID);
tblGames['Player2_ID'] := StrToInt(P2_ID);
tblGames['Player1_score'] := StrToInt(P1_Score);
tblGames['Player2_Score'] := StrToInt(P2_Score);
tblGames['Draw'] := Draw;
tblGames['Winner'] := WinnerName; //How do I get WinnerName(?)
tblGames.Post;
end;
END;
You don't need to do a lot of code. You can let MySQL engine do job for you. Execute the following quires in same order they appeared. This will update the table data as you want.
/* 1: Set all games to draw */
UPDATE Games SET draw = true;
/* 2: Update when Player1 is winner :*/
UPDATE Games, Players SET
Games.draw = false,
Games.winner = CONCAT(Players.first_name, ' ', Players.last_name)
WHERE
(Games.player1_score > Games.player2_score) AND (Games.player1_id=Players.ID);
/* 3: Update when Player2 is winner */
UPDATE Games, Players SET
Games.draw = false,
Games.winner = CONCAT(Players.first_name, ' ', Players.last_name)
WHERE
(Games.player2_score > Games.player1_score) AND (Games.player2_id=Players.ID);
I need to check if there has been a change in a certain part of the application and therefore I make "copies" of the data after loading them and then compare them. One part of the comparison function involves checking keys in dictionaries like lDict1.Keys.EqualsTo(lDict2.Keys).
Although the dictionaries do not rely on the order of the elements, I didn't realize that even if I fill two dictionaries with the same data, they won't be created the same and the order of elements may change, so the previous function does not work properly because it relies on the elements order that may not match when using any of the following methods. (I'm not sure why)
var
lDict1, lDict2 : IDictionary<Integer, TObject>;
lKey : Integer;
begin
lDict1 := TCollections.CreateDictionary<Integer, TObject>;
lDict1.Add(5, nil); // Keys.First = 5, Keys.Last = 5
lDict1.Add(6, nil); // Keys.First = 5, Keys.Last = 6
lDict2 := TCollections.CreateDictionary<Integer, TObject>;
lDict2.AddRange(lDict1); // Keys.First = 6, Keys.Last = 5
lDict2.Clear;
for lKey in lDict1.Keys do // Keys.First = 6, Keys.Last = 5
lDict2.Add(lKey, nil);
end;
Is there any way to make an exact copy of the dictionary so I can compare them? One way to work around this problem is to create my own comparison function, but I'd like to avoid that.
function ContainsSameValues<T>(AEnumerable1, AEnumerable2: IEnumerable<T>): Boolean;
var
lValue : T;
begin
Result := AEnumerable1.Count = AEnumerable2.Count;
if Result then
begin
for lValue in AEnumerable1 do
begin
Result := AEnumerable2.Contains(lValue);
if not Result then
Exit;
end;
end;
end;
usage
ContainsSameValues<Integer>(lDict1.Keys, lDict2.Keys);
Checking for equality of a unordered dictionaries is a relatively simple algorithm. I will outline it here. Suppose we have two dictionaries, A and B.
Compare the number of elements of A and B. If this differs, the dictionaries are not equal.
Enumerate each key/value pair k,v in A. If k is not in B, or B[k] is not equal to v, then the dictionaries are not equal.
If you reach the end of the enumeration, then you know that the dictionaries are equal.
i want to get back ref cursor for the below sp. But it's not working.. not getting any records.. So please help me for this.
DATA_INPUTLIST - it's collection type for two variables (mtn, mtnEffDate)
DATA_RESULTLIST - It's also a collection type for 3 variables (id, effDate, mtn)
CREATE OR REPLACE PROCEDURE proc1 (
pCustId IN NUMBER,
pAcctNo IN NUMBER,
pSearchCriteria IN DATA_INPUTLIST,
pRecordSet OUT SYS_REFCURSOR,
out_error_code OUT NUMBER,
out_error_message OUT VARCHAR2
) AS
--Variables
v_SUN_DATE DATE := TO_DATE('01/15/2011', 'mm/dd/yyyy');
vCount NUMBER := 0;
v_mtn NUM
BER;
v_mtn_eff_date DATE;
cMtnPricePlanInfo DATA_RESULTLIST;
BEGIN
SELECT COUNT(*) INTO vCount FROM TABLE (pSearchCriteria);
FOR i IN 1..vCount LOOP
SELECT MTN, TO_DATE(MTN_EFF_DATE, 'mm/dd/yyyy') into v_mtn, v_mtn_eff_date
FROM TABLE (pSearchCriteria)
WHERE
ROWNUM = i;
SELECT
A.PPLAN_ID, A.EFF_DATE, A.MTN INTO cMtnPricePlanInfo(i).PPLAN_ID, cMtnPricePlanInfo(i).EFF_DATE, cMtnPricePlanInfo(i).MTN
FROM CUST_ACCT_LINE_PPLAN A, CUST_ACCT_LINE_PPLAN_HIST B
WHERE
A.CUST_ID = pCustId
AND A.ACCT_NO = pAcctNo
AND A.MTN = v_mtn
AND A.MTN_EFF_DATE = v_mtn_eff_date
AND A.EFF_DATE >=
(SELECT MAX(EFF_DATE) FROM CUST_ACCT_LINE_PPLAN_HIST C
WHERE
C.CUST_ID = pCustId
AND C.ACCT_NO = pAcctNo
AND C.MTN = v_mtn
AND C.MTN_EFF_DATE = v_mtn_eff_date
AND C.EFF_DATE <= v_SUN_DATE)
AND A.CUST_ID = B.CUST_ID
AND A.ACCT_NO = B.ACCT_NO
AND A.MTN = B.MTN
AND A.MTN_EFF_DATE = B.MTN_EFF_DATE
AND A.PPLAN_ID = B.PPLAN_ID;
END LOOP;
OPEN pRecordSet FOR
SELECT * FROM TABLE (cMtnPricePlanInfo);
END;
/
The first things that stands out to me is the following:
SELECT MTN, TO_DATE(MTN_EFF_DATE, 'mm/dd/yyyy') into v_mtn, v_mtn_eff_date
FROM TABLE (pSearchCriteria)
WHERE
ROWNUM = i;
For i greater than 1 this will not return anything. For the reason why, see this question. In fact, because you're using SELECT ... INTO ..., you'll get a no data found error if i is greater than or equal to 2.
You don't need an SQL query just to fetch some values out of PL/SQL collections. Try replacing this query with
v_mtn := pSearchCriteria(i).MTN;
v_mtn_eff_date := TO_DATE(pSearchCriteria(i).MTN_EFF_DATE, 'mm/dd/yyyy');
I don't have your tables nor the data in them so I can't be sure why you're getting no data. I can only hazard at some obvious suggestions: is vCount zero? If you put suitable values for v_mtn and v_mtn_eff_date and run your query on its own, separate from this stored procedure, does it return any rows?
I am using insertion sort to sort a stringlist (EmailingListArray below).
EmailingListArray[1] is an array that contains names.
EmailingListArray[2] contains corresponding emails.
I am sorting EmailingListArray[1] and when something changes within it, it also changes the second array, so they are sorted together.
An awkward way of doing things, I know, but it's for coursework and I wanted to put an insertion sort in somewhere to try get an extra mark :L
Here's my code
//quick check to make sure array contains correct values
for first := 0 to EmailingListArray[1].Count do
ShowMessage(EmailingListArray[1][first]);
//then sort
First := 0;
Last := EmailingListArray[1].Count;
for CurrentPointer := First +1 to Last-1 do
begin
CurrentValue := EmailingListArray[1][CurrentPointer];
CurrentValue2 := EmailingListArray[2][CurrentPointer];
Pointer := CurrentPointer + 1;
while ((EmailingListArray[1][Pointer] > CurrentValue) AND (Pointer > 0)) do
begin
EmailingListArray[1][Pointer+1] := EmailingListArray[1][Pointer];
EmailingListArray[2][Pointer+1] := EmailingListArray[2][Pointer];
pointer := Pointer -1;
end;
EmailingListArray[1][Pointer + 1] := CurrentValue;
EmailingListArray[2][Pointer + 1] := CurrentValue;
end;
//show message at the end for a check
ShowMessage('hello?');
The message "hello?" isn't being displayed for some reason :S.
The program isn't crashing or anything so it really should atleast display "hello?" at the end.
It isn't sorting my arrays either.
Neither am I sure if the algorithm is written correctly, I got it out of our textbook.
Any help would be much appreciated!
If you want to get a good mark:
Avoid giving misleading names for your variables:
CurrentPointer should be called CurrentIndex or CurrentPosition as it is an index and not a Pointer
Pointer is to be avoided (reserved for Pointer type) and more so because it is not a Pointer; should be WorkIndex or WorkPosition
Read the Insertion sort algorithm (wikipedia has a simple pseudocode for array indexed from 0) and implement it properly:
WorkIndex := CurrentIndex - 1; // - not + in your "Pointer := CurrentPointer + 1;"
Get your Index range from 0 to Count-1 for a TStrings.
Don't mix up the 2 arrays:
EmailingListArray[2][WorkIndex + 1] := CurrentValue2; // not CurrentValue
Update: Missed the bad while condition for zero based array.
2bis. While condition should be with >=0, not >0
while ((EmailingListArray[1][WorkIndex] > CurrentValue) AND (WorkIndex >= 0)) do
Hello could you please help me with the following. I have created a scattered chart and draw a chart from data of a column. The used data is not just after the cell which determines the label:
Column O:
Pwm1 <-- This is the cell I want to see as the label
27114 <-- not used data for graph
27055 <-- etc
27092
27070 <-- data for graph starts here
27105
27024
27092 <-- data for graph ends here
I would like the LABEL cell to appear as the Y column label name (Is now 'Column O'), but how?
This as far as I got (code is Delphi but if someone could help me with a basic example that's ok too):
(* Turn the symbol of the data points off *)
oChart.Diagram.SymbolType := _chartChartSymbolTypeNONE;
oDataSeries := oChart.getUsedData;
oDataSequences := oDataSeries.getDataSequences;
ShowMessage(oDataSequences[1].Label.SourceRangeRepresentation);
SourceRangeRepresentation returns the current label, but how to change?
Thanks Ad
This did it:
(*
creat new DataSequence from range representaion
that provides real data and its role in the series
oDataProvider: com.sun.star.chart2.data.XDataProvider
sRangeRepresentation: range address e.g. Sheet1.A1:B2
sRole: role is defined in com.sun.star.chart2.data.DataSequenceRole
*)
Function CreateDataSequence( oDataProvider : Variant; sRangeRepresentation : String; sRole :String ) : Variant;
Var
oDataSequence : Variant;
Begin
(* create .chart2.data.DataSequence from range representation *)
oDataSequence := oDataProvider.createDataSequenceByRangeRepresentation(sRangeRepresentation);
If NOT VarIsEmpty(oDataSequence) Then
oDataSequence.Role := sRole;
Result := oDataSequence;
End;
oNewLabel := CreateDataSequence(oChart.getDataProvider, '$Sheet1.$O$7', 'label');
oDataSequences[1].setLabel(oNewLabel);