Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 85 additions & 1 deletion Excelize.Tests/UnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public void TestStyle()
}

[Fact]
public void TesttreamWriter()
public void TestStreamWriter()
{
var f = Excelize.NewFile();
Assert.Null(
Expand Down Expand Up @@ -409,11 +409,95 @@ public void TestAddFormControl()
Assert.Null(
Record.Exception(() =>
{
f.AddFormControl(
"Sheet1",
new FormControl
{
Cell = "A3",
Macro = "Button1_Click",
Width = 140,
Height = 60,
Text = "Button 1\r\n",
Paragraph = new RichTextRun[]
{
new()
{
Font = new Font
{
Bold = true,
Italic = true,
Underline = "single",
Family = "Times New Roman",
Size = 14,
Color = "777777",
},
Text = "C1=A1+B1",
},
},
Type = FormControlType.FormControlButton,
Format = new GraphicOptions
{
PrintObject = true,
Positioning = "absolute",
},
}
);
f.AddFormControl(
"Sheet1",
new FormControl
{
Cell = "A1",
Macro = "Button1_Click",
Text = "Option Button 1",
Type = FormControlType.FormControlOptionButton,
}
);
f.AddFormControl(
"Sheet1",
new FormControl
{
Cell = "B1",
Type = FormControlType.FormControlSpinButton,
Width = 15,
Height = 40,
CurrentVal = 7,
MinVal = 5,
MaxVal = 10,
IncChange = 1,
CellLink = "A1",
}
);
f.AddFormControl(
"Sheet1",
new FormControl
{
Cell = "B3",
Type = FormControlType.FormControlScrollBar,
Width = 140,
Height = 20,
CurrentVal = 50,
MinVal = 10,
MaxVal = 100,
PageChange = 1,
CellLink = "A1",
Horizontally = true,
}
);
f.AddFormControl("Sheet1", null);
f.AddVBAProject(
System.IO.File.ReadAllBytes(
Path.GetFullPath(Path.Combine("..", "..", "..", "vbaProject.bin"))
)
);
})
);
var err = Assert.Throws<RuntimeError>(() =>
f.AddFormControl("SheetN", new FormControl { })
);
Assert.Equal("sheet SheetN does not exist", err.Message);
Assert.Null(
Record.Exception(() =>
{
f.SaveAs("TestAddFormControl.xlsm");
})
);
Expand Down
159 changes: 159 additions & 0 deletions Excelize/Excelize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ internal static extern IntPtr AddComment(
ref TypesC.Comment comment
);

[DllImport(
LibraryName,
CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi
)]
internal static extern IntPtr AddFormControl(
long fileIdx,
string sheet,
ref TypesC.FormControl options
);

[DllImport(
LibraryName,
CallingConvention = CallingConvention.Cdecl,
Expand Down Expand Up @@ -1327,6 +1338,154 @@ public unsafe void AddComment(string sheet, Comment? options = null)
throw new RuntimeError(err);
}

/// <summary>
/// AddFormControl provides the method to add form control object in a
/// worksheet by given worksheet name and form control options.
/// Supported form control type: button, check box, group box, label,
/// option button, scroll bar and spinner. If set macro for the form
/// control, the workbook extension should be XLSM or XLTM. Scroll value
/// must be between 0 and 30000. Please note that if a cell link is set
/// for a checkbox form control, Excelize will not assign a value to the
/// linked cell when the checkbox is checked. To reflect the checkbox
/// state, please use the <c>SetCellValue</c> function to manually set
/// the linked cell's value to <c>true</c>.
/// <example>
/// </example>
/// Example 1, add button form control with macro, rich-text, custom
/// button size, print property on Sheet1!A2, and let the button do not
/// move or size with cells:
/// <code>
/// try
/// {
/// f.AddFormControl(
/// "Sheet1",
/// new FormControl
/// {
/// Cell = "A2",
/// Macro = "Button1_Click",
/// Width = 140,
/// Height = 60,
/// Text = "Button 1\r\n",
/// Paragraph = new RichTextRun[]
/// {
/// new()
/// {
/// Font = new Font
/// {
/// Bold = true,
/// Italic = true,
/// Underline = "single",
/// Family = "Times New Roman",
/// Size = 14,
/// Color = "777777",
/// },
/// Text = "C1=A1+B1",
/// },
/// },
/// Type = FormControlType.FormControlButton,
/// Format = new GraphicOptions
/// {
/// PrintObject = true,
/// Positioning = "absolute",
/// },
/// }
/// );
/// }
/// catch (RuntimeError err)
/// {
/// Console.WriteLine(err.Message);
/// }
/// </code>
/// Example 2, add option button form control with checked status and
/// text on Sheet1!A1:
/// <code>
/// try
/// {
/// f.AddFormControl(
/// "Sheet1",
/// new FormControl
/// {
/// Cell = "A1",
/// Macro = "Button1_Click",
/// Text = "Option Button 1",
/// Type = FormControlType.FormControlOptionButton,
/// }
/// );
/// }
/// catch (RuntimeError err)
/// {
/// Console.WriteLine(err.Message);
/// }
/// </code>
/// Example 3, add spin button form control on Sheet1!B1 to increase or
/// decrease the value of Sheet1!A1:
/// <code>
/// try
/// {
/// f.AddFormControl(
/// "Sheet1",
/// new FormControl
/// {
/// Cell = "B1",
/// Type = FormControlType.FormControlSpinButton,
/// Width = 15,
/// Height = 40,
/// CurrentVal = 7,
/// MinVal = 5,
/// MaxVal = 10,
/// IncChange = 1,
/// CellLink = "A1",
/// }
/// );
/// }
/// catch (RuntimeError err)
/// {
/// Console.WriteLine(err.Message);
/// }
/// </code>
/// Example 4, add horizontally scroll bar form control on Sheet1!A2 to
/// change the value of Sheet1!A1 by click the scroll arrows or drag
/// the scroll box:
/// <code>
/// try
/// {
/// f.AddFormControl(
/// "Sheet1",
/// new FormControl
/// {
/// Cell = "A2",
/// Type = FormControlType.FormControlScrollBar,
/// Width = 140,
/// Height = 20,
/// CurrentVal = 50,
/// MinVal = 10,
/// MaxVal = 100,
/// PageChange = 1,
/// CellLink = "A1",
/// Horizontally = true,
/// }
/// );
/// }
/// catch (RuntimeError err)
/// {
/// Console.WriteLine(err.Message);
/// }
/// </code>
/// </summary>
/// <param name="sheet">The worksheet name</param>
/// <param name="options">The form control options</param>
/// <exception cref="RuntimeError">Return None if no error occurred,
/// otherwise raise a RuntimeError with the message.</exception>
public unsafe void AddFormControl(string sheet, FormControl? options = null)
{
if (options == null)
return;
var opts = (TypesC.FormControl)Lib.CsToC(options, new TypesC.FormControl());
string err = Marshal.PtrToStringAnsi(Lib.AddFormControl(FileIdx, sheet, ref opts));
if (!string.IsNullOrEmpty(err))
throw new RuntimeError(err);
}

/// <summary>
/// Add picture in a sheet by given picture format set (such as offset,
/// scale, aspect ratio setting and print settings) and file path.
Expand Down
2 changes: 1 addition & 1 deletion Excelize/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

!["excelize-cs logo"](https://raw.githubusercontent.com/xuri/excelize-cs/main/Excelize/excelize-cs.png)

[!["NuGet version"](https://img.shields.io/nuget/v/ExcelizeCs.svg)](https://www.nuget.org/packages/ExcelizeCs)
[!["NuGet version"](https://img.shields.io/nuget/v/ExcelizeCs.svg?color=%23007ec6)](https://www.nuget.org/packages/ExcelizeCs)
[!["Build Status"](https://github.com/xuri/excelize-cs/actions/workflows/build.yml/badge.svg)](https://github.com/xuri/excelize-cs/actions/workflows/build.yml)
[!["Code Coverage"](https://codecov.io/gh/xuri/excelize-cs/branch/main/graph/badge.svg)](https://codecov.io/gh/xuri/excelize-cs)
[!["Licenses"](https://img.shields.io/badge/license-bsd-orange.svg)](https://opensource.org/licenses/BSD-3-Clause)
Expand Down
67 changes: 67 additions & 0 deletions Excelize/TypesC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,32 @@ public unsafe struct Comment
public RichTextRun* Paragraph;
}

[StructLayout(LayoutKind.Sequential)]
public unsafe struct FormControl
{
public sbyte* Cell;
public sbyte* Macro;
public uint Width;
public uint Height;

[MarshalAs(UnmanagedType.I1)]
public bool Checked;
public uint CurrentVal;
public uint MinVal;
public uint MaxVal;
public uint IncChange;
public uint PageChange;

[MarshalAs(UnmanagedType.I1)]
public bool Horizontally;
public sbyte* CellLink;
public sbyte* Text;
public int ParagraphLen;
public RichTextRun* Paragraph;
public uint Type;
public GraphicOptions Format;
}

[StructLayout(LayoutKind.Sequential)]
public unsafe struct ChartNumFmt
{
Expand Down Expand Up @@ -358,13 +384,22 @@ public unsafe struct Chart
[StructLayout(LayoutKind.Sequential)]
public unsafe struct PivotTableField
{
[MarshalAs(UnmanagedType.I1)]
public bool Compact;
public sbyte* Data;
public sbyte* Name;

[MarshalAs(UnmanagedType.I1)]
public bool Outline;

[MarshalAs(UnmanagedType.I1)]
public bool ShowAll;

[MarshalAs(UnmanagedType.I1)]
public bool InsertBlankRow;
public sbyte* Subtotal;

[MarshalAs(UnmanagedType.I1)]
public bool DefaultSubtotal;
public int NumFmt;
}
Expand All @@ -383,21 +418,53 @@ public unsafe struct PivotTableOptions
public PivotTableField* Data;
public int FilterLen;
public PivotTableField* Filter;

[MarshalAs(UnmanagedType.I1)]
public bool RowGrandTotals;

[MarshalAs(UnmanagedType.I1)]
public bool ColGrandTotals;

[MarshalAs(UnmanagedType.I1)]
public bool ShowDrill;

[MarshalAs(UnmanagedType.I1)]
public bool UseAutoFormatting;

[MarshalAs(UnmanagedType.I1)]
public bool PageOverThenDown;

[MarshalAs(UnmanagedType.I1)]
public bool MergeItem;

[MarshalAs(UnmanagedType.I1)]
public bool ClassicLayout;

[MarshalAs(UnmanagedType.I1)]
public bool CompactData;

[MarshalAs(UnmanagedType.I1)]
public bool ShowError;

[MarshalAs(UnmanagedType.I1)]
public bool ShowRowHeaders;

[MarshalAs(UnmanagedType.I1)]
public bool ShowColHeaders;

[MarshalAs(UnmanagedType.I1)]
public bool ShowRowStripes;

[MarshalAs(UnmanagedType.I1)]
public bool ShowColStripes;

[MarshalAs(UnmanagedType.I1)]
public bool ShowLastColumn;

[MarshalAs(UnmanagedType.I1)]
public bool FieldPrintTitles;

[MarshalAs(UnmanagedType.I1)]
public bool ItemPrintTitles;
public sbyte* PivotTableStyleName;
}
Expand Down
Loading