Monthly Archives: Maj 2013

DataGridView – płynne przewijanie zawartości

2013-05-19

Przy dużych zbiorach danych prezentowanych w kontrolce DataGridView może pojawić się problem z płynnością ich przewijania. Sposobem na wyeliminowanie tego efektu jest ustawienie właściwości DoubleBuffered na true. Jest to właściwość protected więc mamy dwie możliwości: stworzyć własną klasę dziedziczącą po DataGridView i w niej ustawić wartość właściwości DoubleBuffered lub stworzyć metodę rozszerzającą, która przy użyciu refleksji odwoła się do omawianej właściwości i ustawi jej wartość. Poniżej znajduje się implementacja drugiego z wymienionych sposobów:

public static class DataGridViewExtensions
{
	public static void DoubleBuffered(this DataGridView dgv, bool setting)
	{
		Type dgvType = dgv.GetType();
		PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
			BindingFlags.Instance | BindingFlags.NonPublic);
		pi.SetValue(dgv, setting, null);
	}
}

Użycie powyższej metody:

dataGridView1.DoubleBuffered(true);

Dzięki właściwości DoubleBuffered jesteśmy w stanie wyeliminować problemy z brakiem płynności oraz odświeżaniem kontrolki DataGridView podczas przewijania jej zawartości.

T-SQL – kilka przykładów zastosowania tabeli liczb całkowitych

2013-05-09

W poprzednim wpisie pokazałem kilka sposobów na wygenerowanie zbioru kolejnych liczb całkowitych. Dzisiaj zaprezentuję wykorzystanie tych danych w kilku przypadkach. Zacznijmy od przygotowania tabeli zawierającej 100 liczb, będzie ona używana w każdym z prezentowanych przykładów:

declare @Numbers table (N int);
with Numbers
as
(
    select 1 as Number
    union all
    select Number + 1 from Numbers where Number < 100
)
insert into @Numbers(N)
select Number from Numbers option (maxrecursion 100)

Generowanie dat

Poniższe zapytanie zwraca daty oraz informację o dniu tygodnia dla wszystkich dni znajdujących się pomiędzy dwoma datami:

set datefirst 1
declare @beginDate date = '20130501', @endDate date = '20130731'

select
	DateAdd(dd, N - 1, @beginDate) as [Date],
	case DatePart(dw, DateAdd(dd, N - 1, @beginDate))
		when 1 then 'Pn'
		when 2 then 'Wt'
		when 3 then 'Śr'
		when 4 then 'Cz'
		when 5 then 'Pi'
		when 6 then 'So'
		when 7 then 'Ni'
	end as [WeekDay]
from @Numbers
where DateAdd(dd, N - 1, @beginDate) <= @endDate

tally1

Luki w numeracji

Załóżmy, że mamy tabelę zawierającą określone wartości liczbowe:

declare @Values table (value int)
insert into @Values (value)
values (1),(3),(4),(5),(8),(10)

select * from @Values

tally2

Poniżej znajduje się zapytanie zwracające luki w numeracji:

declare @minValue int, @maxValue int
select @minValue = min(value), @maxValue = max(value)
from @Values

select N as Value
from @Numbers n
	left join @Values v on v.value = n.N
where n.N between @minValue and @maxValue
	and v.value is null

tally3

Pozycje występowania danego znaku w tekście

Zapytanie zwraca numery pozycji w tekście, na których znajduje się określony znak:

declare @text varchar(100) = 'to jest przykładowy tekst'
declare @char char(1) = 't'

select N as [CharIndex]
from @Numbers
where SubString(@text, N, 1) = @char and N <= Len(@text)

tally4

Litery występujące w tekście

Poniższe zapytanie zwraca wszystkie litery z podanego tekstu wraz z kodami Ascii oraz liczbą wystąpień:

declare @text varchar(100) = 'to jest przykładowy tekst'

select
	SubString(@text, N, 1) as [Char],
	Ascii(SubString(@text, N, 1)) as [Ascii],
	Count(*) as [Count]
from @Numbers
where N <= Len(@text)
group by SubString(@text, N, 1)

tally5

Podział tekstu na wyrazy

Zapytanie zwraca wszystkie fragmenty danego tekstu rozdzielone określonym znakiem:

declare @text varchar(100) = 'to jest przykładowy tekst'
declare @char char(1) = ' '

set @text = @char + @text + @char

select SubString(@text, N + 1,
        CharIndex(@char, @text, N + 1) - N - 1) as [Words]
from @Numbers
where SubString(@text, N, 1) = @char and N < Len(@text)

tally6

T-SQL – generowanie zbioru kolejnych liczb całkowitych

2013-05-08

Często podczas programowania w T-SQL pojawia się potrzeba skorzystania ze zbioru kolejnych liczb całkowitych z określonego zakresu. SQL Server nie posiada gotowej tabeli zawierającej takie dane, pozostaje opracowanie własnego rozwiązania. Poniżej znajdują się trzy przykłady kodu generującego zbiór kolejnych liczb całkowitych z zakresu od 1 do 195. Skrypty nie korzystają z żadnych obiektów bazy danych (tabele systemowe, widoki), nie opierają się również na pętli while co jest częstym ale mało wydajnym podejściem.

Skrypt 1:

with Numbers
as
(
	select 1 as Number
	union all
	select Number + 1 from Numbers where Number < 195
)
select Number from Numbers option (maxrecursion 195)

Skrypt 2:

select top 195 (a * 10 + b) as Number
from
(
	values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),
		(11),(12),(13),(14),(15),(16),(17),(18),(19)
) as A(a),
(
	values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
) as B(b)
order by 1

Skrypt 3:

with Numbers
as
(
	select a
	from
	(
		values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
	) as A(a)
)
select top 195 row_number() over(order by @@spid) as Number
from Numbers as a, Numbers as b, Numbers as c

W kolejnym wpisie pokażę kilka przykładów zastosowania wygenerowanego w ten sposób zbioru liczb do rozwiązania określonych problemów.