Skip to content

Commit f2d2d14

Browse files
committed
Add new function: AutoFilter
- Update unit test
1 parent 1e36909 commit f2d2d14

File tree

4 files changed

+181
-0
lines changed

4 files changed

+181
-0
lines changed

Excelize.Tests/UnitTest.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,37 @@ public void TestAddSparkline()
877877
Assert.Empty(f.Close());
878878
}
879879

880+
[Fact]
881+
public void TestAutoFilter()
882+
{
883+
File f = Excelize.NewFile();
884+
Assert.Null(
885+
Record.Exception(() =>
886+
{
887+
f.AutoFilter("Sheet1", "A2:D4", new AutoFilterOptions[] { });
888+
f.AutoFilter(
889+
"Sheet1",
890+
"F2:H4",
891+
new AutoFilterOptions[]
892+
{
893+
new AutoFilterOptions { Column = "F", Expression = "x != blanks" },
894+
}
895+
);
896+
})
897+
);
898+
RuntimeError err = Assert.Throws<RuntimeError>(() =>
899+
f.AutoFilter("SheetN", "L1:N4", new AutoFilterOptions[] { })
900+
);
901+
Assert.Equal("sheet SheetN does not exist", err.Message);
902+
Assert.Null(
903+
Record.Exception(() =>
904+
{
905+
f.SaveAs("TestAutoFilter.xlsx");
906+
})
907+
);
908+
Assert.Empty(f.Close());
909+
}
910+
880911
[StructLayout(LayoutKind.Sequential)]
881912
public unsafe struct C1
882913
{

Excelize/Excelize.cs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,15 @@ ref TypesC.Table opts
166166
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
167167
internal static extern IntPtr AddVBAProject(long fileIdx, byte[] b, int bLen);
168168

169+
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
170+
internal static extern IntPtr AutoFilter(
171+
long fileIdx,
172+
[MarshalAs(UnmanagedType.LPUTF8Str)] string sheet,
173+
[MarshalAs(UnmanagedType.LPUTF8Str)] string range,
174+
[In, MarshalAs(UnmanagedType.LPArray)] TypesC.AutoFilterOptions[] options,
175+
int length
176+
);
177+
169178
[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
170179
internal static extern TypesC.CellNameToCoordinatesResult CellNameToCoordinates(
171180
[MarshalAs(UnmanagedType.LPUTF8Str)] string cell
@@ -2185,6 +2194,131 @@ public void AddVBAProject(byte[] buffer)
21852194
throw new RuntimeError(err);
21862195
}
21872196

2197+
/// <summary>
2198+
/// Adds an auto filter to a worksheet using the specified sheet name,
2199+
/// range reference, and filter options.
2200+
///
2201+
/// An auto filter in Excel provides a way to filter a 2D range of data
2202+
/// based on simple criteria. For example, to apply an auto filter to
2203+
/// the range <c>A1:D4</c> on the worksheet "Sheet1":
2204+
///
2205+
/// <code><![CDATA[
2206+
/// f.AutoFilter("Sheet1", "A1:D4", Array.Empty<AutoFilterOptions>());
2207+
/// ]]></code>
2208+
///
2209+
/// To filter data within an auto filter:
2210+
///
2211+
/// <code>
2212+
/// f.AutoFilter("Sheet1", "A1:D4", new AutoFilterOptions[]
2213+
/// {
2214+
/// new AutoFilterOptions { Column = "B", Expression = "x != blanks" }
2215+
/// });
2216+
/// </code>
2217+
///
2218+
/// <para>
2219+
/// <b>Column</b> specifies which column in the auto filter range will
2220+
/// apply a filter.
2221+
/// </para>
2222+
///
2223+
/// <para>
2224+
/// Note: Specifying filter conditions alone is not sufficient. Rows
2225+
/// that do not match the filter criteria must also be hidden manually
2226+
/// using <c>SetRowVisible</c>. The library cannot automatically hide
2227+
/// rows because this is outside the Excel file format's capabilities.
2228+
/// </para>
2229+
///
2230+
/// <para>
2231+
/// <b>Expression</b> defines the filter criteria. The following
2232+
/// operators are supported:
2233+
/// </para>
2234+
///
2235+
/// <list type="bullet">
2236+
/// <item><description><c>==</c></description></item>
2237+
/// <item><description><c>!=</c></description></item>
2238+
/// <item><description><c>&gt;</c></description></item>
2239+
/// <item><description><c>&lt;</c></description></item>
2240+
/// <item><description><c>&gt;=</c></description></item>
2241+
/// <item><description><c>&lt;=</c></description></item>
2242+
/// <item><description><c>and</c></description></item>
2243+
/// <item><description><c>or</c></description></item>
2244+
/// </list>
2245+
///
2246+
/// <para>
2247+
/// Expressions may contain a single condition or two conditions
2248+
/// combined using <c>and</c> or <c>or</c>. Examples:
2249+
/// </para>
2250+
///
2251+
/// <code>
2252+
/// x &lt; 2000
2253+
/// x &gt; 2000
2254+
/// x == 2000
2255+
/// x &gt; 2000 and x &lt; 5000
2256+
/// x == 2000 or x == 5000
2257+
/// </code>
2258+
///
2259+
/// <para>
2260+
/// Filtering blank or non-blank values:
2261+
/// </para>
2262+
///
2263+
/// <code>
2264+
/// x == Blanks
2265+
/// x == NonBlanks
2266+
/// </code>
2267+
///
2268+
/// <para>
2269+
/// Simple string matching is also supported:
2270+
/// </para>
2271+
///
2272+
/// <code>
2273+
/// x == b* // begins with b
2274+
/// x != b* // doesn't begin with b
2275+
/// x == *b // ends with b
2276+
/// x != *b // doesn't end with b
2277+
/// x == *b* // contains b
2278+
/// x != *b* // doesn't contain b
2279+
/// </code>
2280+
///
2281+
/// <para>
2282+
/// Wildcards:
2283+
/// </para>
2284+
/// <list type="bullet">
2285+
/// <item><description><c>*</c> matches any sequence of characters or digits.</description></item>
2286+
/// <item><description><c>?</c> matches any single character or digit.</description></item>
2287+
/// <item><description><c>~</c> escapes Excel's wildcard characters.</description></item>
2288+
/// </list>
2289+
///
2290+
/// <para>
2291+
/// In expressions, the placeholder variable (commonly shown as <c>x</c>)
2292+
/// may be any simple string. The actual placeholder name is ignored, so
2293+
/// the following are equivalent:
2294+
/// </para>
2295+
///
2296+
/// <code>
2297+
/// x &lt; 2000
2298+
/// col &lt; 2000
2299+
/// Price &lt; 2000
2300+
/// </code>
2301+
/// </summary>
2302+
/// <param name="sheet">The worksheet name</param>
2303+
/// <param name="range">The top-left and right-bottom cell range reference</param>
2304+
/// <param name="opts"> The auto filter options</param>
2305+
/// <exception cref="RuntimeError">Return None if no error occurred,
2306+
/// otherwise raise a RuntimeError with the message.</exception>
2307+
public void AutoFilter(string sheet, string range, AutoFilterOptions[] opts)
2308+
{
2309+
TypesC.AutoFilterOptions[] arr = new TypesC.AutoFilterOptions[opts.Length];
2310+
for (int i = 0; i < opts.Length; i++)
2311+
{
2312+
arr[i] = (TypesC.AutoFilterOptions)
2313+
Lib.CsToC(opts[i], new TypesC.AutoFilterOptions());
2314+
}
2315+
string err = Marshal.PtrToStringUTF8(
2316+
Lib.AutoFilter(FileIdx, sheet, range, arr, arr.Length)
2317+
);
2318+
if (!string.IsNullOrEmpty(err))
2319+
throw new RuntimeError(err);
2320+
}
2321+
21882322
/// <summary>
21892323
/// Closes and cleanup the open temporary file for the spreadsheet.
21902324
/// </summary>

Excelize/TypesC.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ public struct Protection
118118
public bool Locked;
119119
}
120120

121+
[StructLayout(LayoutKind.Sequential)]
122+
public unsafe struct AutoFilterOptions
123+
{
124+
public sbyte* Column;
125+
public sbyte* Expression;
126+
}
127+
121128
[StructLayout(LayoutKind.Sequential)]
122129
public unsafe struct HeaderFooterOptions
123130
{

Excelize/TypesCs.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,15 @@ public struct Protection
291291
public bool Hidden;
292292
}
293293

294+
/// <summary>
295+
/// AutoFilterOptions directly maps the auto filter settings.
296+
/// </summary>
297+
public struct AutoFilterOptions
298+
{
299+
public string Column;
300+
public string Expression;
301+
}
302+
294303
/// <summary>
295304
/// HeaderFooterOptions directly maps the settings of header and footer.
296305
/// </summary>

0 commit comments

Comments
 (0)