Yorumları: 1.664
Konuları: 20
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 19.042 Üstad
27-02-2019, Saat: 10:45
(Son Düzenleme: 27-02-2019, Saat: 10:47, Düzenleyen: mrmarman.)
Arkadaşlar Selection teriminden yürüyün derim
Microsoft der ki Selection.Adrress size seçili bloğu verir.
Eğer ctrl ile adımlı seçim varsa ilk adımı verir, belirleyeceğiniz aralıktaki her hücreyi dolaşıp ayrı ayrı if in Selection diye sormak gerekiyormuş
Hatta bu deçim içerisinde resim, nesne vb için ayrı sorgu gerekiyor diye laf uzuyor.
özet geçtim.
Saygılarımla
Muharrem ARMAN
Yorumları: 1.664
Konuları: 20
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 19.042 Üstad
28-02-2019, Saat: 13:52
(Son Düzenleme: 28-02-2019, Saat: 18:28, Düzenleyen: mrmarman.)
Bilgisayar başına geçmişken size bir örnek hazırladım.
- Hem soruya cevap olsun, hem de hücrelerin Delphi cephesinden iki farklı şekilde ( CELL ve RANGE olarak) nasıl nitelendikleri konusunda fikir sahibi olunabilsin istedim.
- Excel için öncelikle kurulu ve açık mı kontrolünden sonra
- Selection.Address ile CTRL basılı iken tek tek yapılan seçimleri seçim sırasına göre alıyor.
- Adres eğer bir RANGE aralık ise ( aşağıdaki ekranda uyguladığım $F$8:$H$9 buna bir örnektir) hücre adres bloğunu bileşenlerine ayırıp her birini ayrı birer hücreye CTRL basılmış gibi tekil sonuç döndürüyor.
- Function parametersinde aTip_Range_1_Cells_2_Value_3_ gibi açık anlaşılsın bir paramater ile 1,2 veya 3 ile hangi tipte sonuç almak istediğinizi belirtiyorsunuz.
- Sonuç tablosu için hücre ayracı olarak varsayılan '|' şeklinde belirledim. Bu parametreye değer atamazsanız varsayılan olarak bu kabul edilir. Siz tilda yıldız vs. ne isterseniz koyabilirsiniz.
...
...
...
Kullanımı :
..
...
....
Sonuçlar :
4,5|9,5|6,6|6,5|6,8|8,6|8,7|8,8|9,6|9,7|9,8
$E$4|$E$9|$F$6|$E$6|$H$6|$F$8|$G$8|$H$8|$F$9|$G$9|$H$9
a|f|3|c|z|5||d|6||f
Saygılarımla
Muharrem ARMAN
Yorumları: 1.571
Konuları: 88
Kayıt Tarihi: 09-08-2016
Rep Puanı: 13.829 Üstad
Bence sorulmak istenen, "tüm satır seçili olursa nasıl tespit edilebilir?"
Excelde satır numaralarını gösteren ilk sütuna basıldığında satırın komple seçili hale gelme olayı.
Not: @ mrmarmanın çözümü bunu kapsıyor mudur bilmiyorum. Denemedim.
There's no place like 127.0.0.1
Yorumları: 820
Konuları: 135
Kayıt Tarihi: 07-12-2017
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 3.030 Uzman
Bu dünyada kendine sakladığın bilgi ahirette işine yaramaz.
Yorumları: 1.664
Konuları: 20
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 19.042 Üstad
28-02-2019, Saat: 17:49
(Son Düzenleme: 01-03-2019, Saat: 12:05, Düzenleyen: mrmarman.)
@ SimaWB
Evet kapsıyor ama limitlemek lazım. Keza satırı seçince Selection.Columns.Count ile ilgili değer alınsa da 16384 hücre dolaşmak istemeyiz.
Şöyle bir limit koydum. Son parametreye bir şey yazılmazsa max. 100 tane sütuna bakıyor. Ama siz dilerseniz bu rakamı 200, 500, 1000 dilediğiniz kadar genişletebilirsiniz.
Adresleri ikiye böldük. $6:$6 şeklinde eşit ise satır seçilmiş olduğu anlaşılıyor. Birden fazla satır seçili ise $6:$8 şeklinde oluyor. İkiye böldüğümüz adres $ hariç sadece rakam ise satır seçilmiş demek. Bunun başına $A gibi bir değer eklemek adresi bütünlemek için kafidir.
Uses ActiveX, ComObj;
Function SeciliHucreler( aTip_Range_1_Cells_2_Value_3_: Word; boolSadeceDoluHucreler:Boolean; aSeparator:Char='|'; aMaxCol: Integer = 100; aMaxRow: Integer = 100 ) : String;
type TAdresTipi = ( aNone = 0, aTekHucre, aHucreBlok,
aSatirBoyunca, aSutunBoyunca );
type TExcelAdres = record
AdresTipi : TAdresTipi;
Adr1, Adr2 : String;
x1, y1, x2, y2 : Integer;
end;
function HucreAdresTipi( Excel:OleVariant; strHucreAdr: String; iMaxCol, iMaxRow:Integer ): TExcelAdres;
function IcerikTipi_123( aText: String ) : Byte; // 1 String; 2 Numeric; 3 Mixed
var
boolStr,
boolNum : Boolean;
i : Integer;
begin
boolStr := False;
boolNum := False;
for i := 1 to length(aText) do begin
if CharInSet( aText[i], ['1'..'9', '0'] ) then boolNum := True;
if CharInSet( aText[i], ['a'..'z', 'A'..'Z'] ) then boolStr := True;
end;
if boolNum AND boolStr then Result := 3 // mixed
else
if boolNum then Result := 2 // numeric
else Result := 1; // string
end;
var
i : Integer;
begin
With Result do begin // Varsayılan
AdresTipi := aNone;
Adr1 := '';
Adr2 := '';
x1 := -1;
y1 := -1;
y2 := -1;
x2 := -1;
end;
if Pos(':', strHucreAdr) > 0 then // Seçili Blok Aralık Hücreler
begin
// Blok Hücre ancak hangi tip. aHucreBlok, aSatirBoyunca, aSutunBoyunca
// Parse edelim.
Result.Adr1 := Copy(strHucreAdr, 1, Pos(':', strHucreAdr)-1);
System.Delete(strHucreAdr, 1, Pos(':', strHucreAdr));
Result.Adr2 := strHucreAdr;
// Şimdi Tipi Anlayalım..
Case IcerikTipi_123( Result.Adr1 ) of
1: Result.AdresTipi := aSutunBoyunca; // String
2: Result.AdresTipi := aSatirBoyunca; // Numeric
3: Result.AdresTipi := aHucreBlok // Mixed
end; // case
end else begin
Result.AdresTipi := aTekHucre;
end;
case Result.AdresTipi of
aTekHucre: begin
Result.x1 := Excel.Range[ strHucreAdr ].Column;
Result.y1 := Excel.Range[ strHucreAdr ].Row;
Result.x2 := Excel.Range[ strHucreAdr ].Column;
Result.y2 := Excel.Range[ strHucreAdr ].Row;
end;
aHucreBlok: begin
Result.x1 := Excel.Range[ Result.Adr1 ].Column;
Result.y1 := Excel.Range[ Result.Adr1 ].Row;
Result.x2 := Excel.Range[ Result.Adr2 ].Column;
Result.y2 := Excel.Range[ Result.Adr2 ].Row;
end;
aSatirBoyunca: begin
Result.x1 := Excel.Range[ '$A' + Result.Adr1 ].Column;
Result.y1 := Excel.Range[ '$A' + Result.Adr1 ].Row;
Result.x2 := iMaxCol;
Result.y2 := Excel.Range[ '$A' + Result.Adr2 ].Row;
end;
aSutunBoyunca: begin
Result.x1 := Excel.Range[ Result.Adr1 + '$1' ].Column;
Result.y1 := Excel.Range[ Result.Adr1 + '$1' ].Row;
Result.x2 := Excel.Range[ Result.Adr2 + '$1' ].Column;
Result.y2 := iMaxRow;
end;
end;
end;
function IsExcelActive: boolean;
const ClassName = 'Excel.Application';
var
ClassID : TCLSID; // ActiveX
Unknown : IUnknown;
aExcel : OleVariant;
begin
Result := False;
// EXCEL için Önce Kurulu mu AND sonra Aktif mi Kontrolüdür. //
if Succeeded(CLSIDFromProgID(PWideChar(WideString(ClassName)), ClassID))
AND Succeeded(CLSIDFromProgID(PWideChar(WideString(ClassName)), ClassID))
then Result := Succeeded(GetActiveObject(ClassID, nil, Unknown));
// Hafızada Excel kırıntısı kalmışsa onu test edelim.. "Access Violation" savar...
if Result then
begin
aExcel := GetActiveOleObject('Excel.Application');
Result := (aExcel.Workbooks.Count > 0) AND ( aExcel.WorkSheets.Count > 0 );
aExcel := Unassigned;
end;
end;
Var
aExcel : OleVariant;
aRange : OleVariant;
aExcelAddress : TExcelAdres;
strHucreler,
strHucreAdr,
strHucreValue,
strResult : String;
i, j : Integer;
begin
if IsExcelActive() then
begin // Excel Kurulu ve şu an Açık
aExcel := GetActiveOleObject('Excel.Application');
try
strHucreler := VarToStr( aExcel.Selection.Address );
if strHucreler <> '' then
begin
strHucreler := strHucreler + ',';
while pos(',', strHucreler) > 0 do
begin
strHucreAdr := Trim( Copy(strHucreler, 1, Pos(',', strHucreler)-1 ) );
aExcelAddress := HucreAdresTipi( aExcel, strHucreAdr, aMaxCol, aMaxRow );
case aExcelAddress.AdresTipi of
aTekHucre :
begin
strHucreValue := aExcel.Range[ strHucreAdr ].Text;
Case aTip_Range_1_Cells_2_Value_3_ of
1: strResult := Format('%s,%s', [ aExcel.Range[ strHucreAdr ].Row,
aExcel.Range[ strHucreAdr ].Column ]);
2: strResult := strHucreAdr;
3: strResult := strHucreValue;
end;
if boolSadeceDoluHucreler then
begin
if Trim(strHucreValue) <> '' then
begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
end
else begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
end;
aHucreBlok, aSatirBoyunca, aSutunBoyunca :
begin
// Hücreleri dolaşıyoruz...
i := aExcelAddress.y1;
while i <= aExcelAddress.y2 do
begin
j := aExcelAddress.x1;
while j <= aExcelAddress.x2 do
begin
strHucreValue := aExcel.Cells[ i, j ].Text;
Case aTip_Range_1_Cells_2_Value_3_ of
1: strResult := Format('%d,%d', [i,j]);
2: strResult := aExcel.Cells[ i, j ].Address;
3: strResult := strHucreValue;
end;
if boolSadeceDoluHucreler then
begin
if Trim(strHucreValue) <> '' then
begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
end
else begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
inc(j);
end;
inc(i);
end;
end;
end; // Case
System.Delete( strHucreler, 1, Pos(',', strHucreler));
end; // While
end;
finally
aExcel := Unassigned;
end;
end else Exit;
end;
Yeni Kullanım Şekli.
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Memo1.Lines.Add( SeciliHucreler( 1, True, '|', 100, 100 ) );
Memo1.Lines.Add( SeciliHucreler( 2, True, '|', 100, 100 ) );
Memo1.Lines.Add( SeciliHucreler( 3, True, '|', 100, 100 ) );
end;
Saygılarımla
Muharrem ARMAN
Yorumları: 178
Konuları: 57
Kayıt Tarihi: 07-08-2018
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 79 Başlangıç
Teşekkürümü ifade etmek için söz bulamadım. Allah razı olsun, ne dilerseniz dileyin, Allah gönlünüze göre versin.
Yorumları: 1.664
Konuları: 20
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 19.042 Üstad
@ ahmetb
Bu ve benzer konular kendi kendimize meydan okuma (challenge) tipinde, normal hayatta ihtiyacımız olmasa da içinden bir ders çıkarmak adına keyif aldığım bir konu oldu.
Ben teşekkür ederim. Ben de çözüm adına kod arşivime yeni bir burç eklemiş oldum.
Saygılarımla
Muharrem ARMAN
Yorumları: 178
Konuları: 57
Kayıt Tarihi: 07-08-2018
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 79 Başlangıç
03-03-2019, Saat: 19:27
(Son Düzenleme: 03-03-2019, Saat: 19:28, Düzenleyen: ahmetb.)
(28-02-2019, Saat: 17:49)mrmarman Adlı Kullanıcıdan Alıntı: @SimaWB
Evet kapsıyor ama limitlemek lazım. Keza satırı seçince Selection.Columns.Count ile ilgili değer alınsa da 16384 hücre dolaşmak istemeyiz.
Şöyle bir limit koydum. Son parametreye bir şey yazılmazsa max. 100 tane sütuna bakıyor. Ama siz dilerseniz bu rakamı 200, 500, 1000 dilediğiniz kadar genişletebilirsiniz.
Adresleri ikiye böldük. $6:$6 şeklinde eşit ise satır seçilmiş olduğu anlaşılıyor. Birden fazla satır seçili ise $6:$8 şeklinde oluyor. İkiye böldüğümüz adres $ hariç sadece rakam ise satır seçilmiş demek. Bunun başına $A gibi bir değer eklemek adresi bütünlemek için kafidir.
Uses ActiveX, ComObj;
Function SeciliHucreler( aTip_Range_1_Cells_2_Value_3_: Word; boolSadeceDoluHucreler:Boolean; aSeparator:Char='|'; aMaxCol: Integer = 100; aMaxRow: Integer = 100 ) : String;
type TAdresTipi = ( aNone = 0, aTekHucre, aHucreBlok,
aSatirBoyunca, aSutunBoyunca );
type TExcelAdres = record
AdresTipi : TAdresTipi;
Adr1, Adr2 : String;
x1, y1, x2, y2 : Integer;
end;
function HucreAdresTipi( Excel:OleVariant; strHucreAdr: String; iMaxCol, iMaxRow:Integer ): TExcelAdres;
function IcerikTipi_123( aText: String ) : Byte; // 1 String; 2 Numeric; 3 Mixed
var
boolStr,
boolNum : Boolean;
i : Integer;
begin
boolStr := False;
boolNum := False;
for i := 1 to length(aText) do begin
if CharInSet( aText[i], ['1'..'9', '0'] ) then boolNum := True;
if CharInSet( aText[i], ['a'..'z', 'A'..'Z'] ) then boolStr := True;
end;
if boolNum AND boolStr then Result := 3 // mixed
else
if boolNum then Result := 2 // numeric
else Result := 1; // string
end;
var
i : Integer;
begin
With Result do begin // Varsayılan
AdresTipi := aNone;
Adr1 := '';
Adr2 := '';
x1 := -1;
y1 := -1;
y2 := -1;
x2 := -1;
end;
if Pos(':', strHucreAdr) > 0 then // Seçili Blok Aralık Hücreler
begin
// Blok Hücre ancak hangi tip. aHucreBlok, aSatirBoyunca, aSutunBoyunca
// Parse edelim.
Result.Adr1 := Copy(strHucreAdr, 1, Pos(':', strHucreAdr)-1);
System.Delete(strHucreAdr, 1, Pos(':', strHucreAdr));
Result.Adr2 := strHucreAdr;
// Şimdi Tipi Anlayalım..
Case IcerikTipi_123( Result.Adr1 ) of
1: Result.AdresTipi := aSutunBoyunca; // String
2: Result.AdresTipi := aSatirBoyunca; // Numeric
3: Result.AdresTipi := aHucreBlok // Mixed
end; // case
end else begin
Result.AdresTipi := aTekHucre;
end;
case Result.AdresTipi of
aTekHucre: begin
Result.x1 := Excel.Range[ strHucreAdr ].Column;
Result.y1 := Excel.Range[ strHucreAdr ].Row;
Result.x2 := Excel.Range[ strHucreAdr ].Column;
Result.y2 := Excel.Range[ strHucreAdr ].Row;
end;
aHucreBlok: begin
Result.x1 := Excel.Range[ Result.Adr1 ].Column;
Result.y1 := Excel.Range[ Result.Adr1 ].Row;
Result.x2 := Excel.Range[ Result.Adr2 ].Column;
Result.y2 := Excel.Range[ Result.Adr2 ].Row;
end;
aSatirBoyunca: begin
Result.x1 := Excel.Range[ '$A' + Result.Adr1 ].Column;
Result.y1 := Excel.Range[ '$A' + Result.Adr1 ].Row;
Result.x2 := iMaxCol;
Result.y2 := Excel.Range[ '$A' + Result.Adr2 ].Row;
end;
aSutunBoyunca: begin
Result.x1 := Excel.Range[ Result.Adr1 + '$1' ].Column;
Result.y1 := Excel.Range[ Result.Adr1 + '$1' ].Row;
Result.x2 := Excel.Range[ Result.Adr2 + '$1' ].Column;
Result.y2 := iMaxRow;
end;
end;
end;
function IsExcelActive: boolean;
const ClassName = 'Excel.Application';
var
ClassID : TCLSID; // ActiveX
Unknown : IUnknown;
aExcel : OleVariant;
begin
Result := False;
// EXCEL için Önce Kurulu mu AND sonra Aktif mi Kontrolüdür. //
if Succeeded(CLSIDFromProgID(PWideChar(WideString(ClassName)), ClassID))
AND Succeeded(CLSIDFromProgID(PWideChar(WideString(ClassName)), ClassID))
then Result := Succeeded(GetActiveObject(ClassID, nil, Unknown));
// Hafızada Excel kırıntısı kalmışsa onu test edelim.. "Access Violation" savar...
if Result then
begin
aExcel := GetActiveOleObject('Excel.Application');
Result := (aExcel.Workbooks.Count > 0) AND ( aExcel.WorkSheets.Count > 0 );
aExcel := Unassigned;
end;
end;
Var
aExcel : OleVariant;
aRange : OleVariant;
aExcelAddress : TExcelAdres;
strHucreler,
strHucreAdr,
strHucreValue,
strResult : String;
i, j : Integer;
begin
if IsExcelActive() then
begin // Excel Kurulu ve şu an Açık
aExcel := GetActiveOleObject('Excel.Application');
try
strHucreler := VarToStr( aExcel.Selection.Address );
if strHucreler <> '' then
begin
strHucreler := strHucreler + ',';
while pos(',', strHucreler) > 0 do
begin
strHucreAdr := Trim( Copy(strHucreler, 1, Pos(',', strHucreler)-1 ) );
aExcelAddress := HucreAdresTipi( aExcel, strHucreAdr, aMaxCol, aMaxRow );
case aExcelAddress.AdresTipi of
aTekHucre :
begin
strHucreValue := aExcel.Range[ strHucreAdr ].Text;
Case aTip_Range_1_Cells_2_Value_3_ of
1: strResult := Format('%s,%s', [ aExcel.Range[ strHucreAdr ].Row,
aExcel.Range[ strHucreAdr ].Column ]);
2: strResult := strHucreAdr;
3: strResult := strHucreValue;
end;
if boolSadeceDoluHucreler then
begin
if Trim(strHucreValue) <> '' then
begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
end
else begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
end;
aHucreBlok, aSatirBoyunca, aSutunBoyunca :
begin
// Hücreleri dolaşıyoruz...
i := aExcelAddress.y1;
while i <= aExcelAddress.y2 do
begin
j := aExcelAddress.x1;
while j <= aExcelAddress.x2 do
begin
strHucreValue := aExcel.Cells[ i, j ].Text;
Case aTip_Range_1_Cells_2_Value_3_ of
1: strResult := Format('%d,%d', [i,j]);
2: strResult := aExcel.Cells[ i, j ].Address;
3: strResult := strHucreValue;
end;
if boolSadeceDoluHucreler then
begin
if Trim(strHucreValue) <> '' then
begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
end
else begin
if Result = ''
then Result := strResult
else Result := Result + aSeparator + strResult;
end;
inc(j);
end;
inc(i);
end;
end;
end; // Case
System.Delete( strHucreler, 1, Pos(',', strHucreler));
end; // While
end;
finally
aExcel := Unassigned;
end;
end else Exit;
end;
Yeni Kullanım Şekli.
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
Memo1.Lines.Add( SeciliHucreler( 1, True, '|', 100, 100 ) );
Memo1.Lines.Add( SeciliHucreler( 2, True, '|', 100, 100 ) );
Memo1.Lines.Add( SeciliHucreler( 3, True, '|', 100, 100 ) );
end;
(01-03-2019, Saat: 19:17)mrmarman Adlı Kullanıcıdan Alıntı: @ahmetb
Bu ve benzer konular kendi kendimize meydan okuma (challenge) tipinde, normal hayatta ihtiyacımız olmasa da içinden bir ders çıkarmak adına keyif aldığım bir konu oldu.
Ben teşekkür ederim. Ben de çözüm adına kod arşivime yeni bir burç eklemiş oldum.
Merhaba; İçinden çıkamadım bir sorunu var. Yardımınızı rica ederim.
Memo1.Lines.Add(SeciliHucreler(3, True, '|', 100, 100));
Add satır alt, alta eklemesi lazımken memoya yan, yana ekliyor. Bu durum normal mi?
A 045|A 348|A 345|A 346|A 049|A 045
Yorumları: 1.664
Konuları: 20
Kayıt Tarihi: 05-08-2016
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 19.042 Üstad
03-03-2019, Saat: 23:36
(Son Düzenleme: 03-03-2019, Saat: 23:39, Düzenleyen: mrmarman.)
normal,
amaç: o satırı bir stringlist'in DelimitedText property'sine atayıp, separator ile DELIMITER belirtip otomatik satırlara dönüşmesini sağlamaktır.
bkz.
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.Delimiter := '|';
SL.DelimitedText := HucreAdresMemoyaEklenenSatir;
// bu aşamada SL[0] içinde A 045, SL[1] içinde A 348 vs. vs. göreceksiniz.
// burada iş bitince de finally free olacak.
finally
SL.Free;
end;
Dilerseniz kendiniz de parse edebilirsiniz.
Saygılarımla
Muharrem ARMAN
Yorumları: 178
Konuları: 57
Kayıt Tarihi: 07-08-2018
Aktif Kullandığınız Delphi Sürümü:
Rep Puanı: 79 Başlangıç
Haklısınız, Ben başka yerden yakaladım kodları.
if Trim(strHucreValue) <> '' then
begin
if Result = '' then
Result := strResult
else
Result := Result + aSeparator + strResult;
Yakala.Add(strResult);
end;
|